Cross-platform (Linux) development based on VS2019 C++ (1.4.2) - with parameter signals

Continuing from the previous article, this chapter will first learn about signals with parameters and functions such as sigqueue and sigaction

Cross-platform (Linux) development based on VS2019 C++ (1.4) - Signal

I. Introduction

The kill function we mentioned in the last article sends a signal only for a certain process, and does not reflect the parameters. It was also mentioned before that data sharing cannot be performed in the process. Even if a global variable is defined and modified between child processes, the parent process does not know whether it has been modified or not. So this situation requires IPC communication to solve, and kill cannot transmit data, then you need to use a signal with parameters

2. Function prototype

1. sigaction library function - binding signal

Function: Used to change the behavior of a process after receiving a specific signal.

Header file <signal.h>

原型: int  sigaction(int signum,const struct sigac        tion *act,const struct sigaction *old);

parameter

  • The first parameter is the value of the signal, which can be any specific valid signal except sigkill and sigstop (define your own processing function for these two signals, which will result in a signal installation error)
  • The second parameter is a pointer to an instance of the structure sigaction. In the instance of the structure sigaction, the processing of a specific signal is specified. It can be empty, and the process will process the signal by default.
  • The object pointed to by the third parameter oldact is used to save the original processing of the corresponding signal, usually null .

Note: Parameters two and three are pointers to structures. The second parameter is the most important . The signal processing function is included in this structure, but the function cannot be directly assigned to the second parameter when it is used.

Return value: The function returns 0 on success, -1 on failure

View the sigaction function in linux as follows

The structure of the corresponding second parameter sigaction is as follows

        There cannot be a function in the c structure, but here only the function pointer is reserved, and it does not break the stipulation that there cannot be a function in the structure. For the structure, it is just a pointer variable (more special, pointing to a function)

        The first one is similar to the function pointer without parameters mentioned above, so we use the second function to implement the signal with parameters, and then use sa_flags to determine whether it has parameters

2, sigqueue library function - send signal

Function: The new system call for sending signals, mainly for real-time signals, supports signals with parameters , and is used in pairs with the function sigaction().

原型:     int sigqueue(pid_t pid, int sig, const union sigval value);

parameter  

  • The first parameter is the process id that specifies the receiving signal
  • The second parameter determines the signal that is about to be sent
  • The third parameter is a union data structure union sigval (similar to structure, rarely used), which specifies the parameters passed by the signal, that is, the so-called 4-byte value.

Return value: 0 for success, -1 for failure

View the sigqueue function in linux as follows 

The corresponding sigval union of the second parameter is as follows 

 Where sigval_int is the integer data to be sent

3. Realization

1. Sample code

This example implements the parent process to send signals and pass data to the child process

①The previous void signalFunc(int i) is only suitable for the use of no-parameter signals, so the redefined function is as follows

void sigaction_func(int num, siginfo_t* info, void* vo)

The first parameter num is the received signal code, and the received data is stored in the second parameter info

② The data sent by sigqueue must be in the form of a consortium

#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include<iostream>
#include <signal.h>
#include<stdio.h>
#include <stdlib.h>
using namespace std;

//带参数的信号
void sigaction_func(int num, siginfo_t* info, void* vo);
int main(){
    int pid = 0;
	//准备结构体
	struct sigaction  act;
	act.sa_sigaction = sigaction_func;
	act.sa_flags = SA_SIGINFO;//带参数的信号
	//绑定信号
	sigaction(SIGUSR1,&act,NULL);  //发送是sigqueue
	
	pid = fork();

	if (pid == 0)
	{
		while (true)
		{
			cout << "子进程运行中 ...pid =" << getpid() << endl;
			sleep(1);
		}
	}
	else if (pid > 0)
	{
		sleep(2);
		//准备要传递的数据
		union sigval value;
		value.sival_int = 111;
		//带参数发送信号
		sigqueue(pid, SIGUSR1, value);//第三个参数跟之前不一样,是一个联合体
		//卡住父进程
		while (1) {}
	}

	return 0;
}

void sigaction_func(int num, siginfo_t* info, void* vo)
{
	int x = info->si_int;
	cout <<"当前进程pid = "<<getpid()<<"  sigaction_func函数被调用了,num =  " << num << "  信号传递过来的数据是 x =  " << x<< endl;
}

2. Running results

4. Summary

The data passed in the previous example is just an integer, so some people may notice the second parameter void * in the sigval union (as shown below), thinking that it can be used to implement other types of data, but this is not the case.

1. When the earliest developers developed signals, they only supported data transfer of int type, so they thought of reserving a void * for subsequent use, but unfortunately, the data transfer of void * is still not supported in the ubuntu20 version, and it has not been carried out yet. Update, so complex data (arrays, structures) cannot be passed, which is very tasteless.

2. Because IPC has five communication methods, it is not only possible to use signals to transfer data between processes, because the troublesome operation of signals makes it only the basic use of communication

3. When the child process receives an unknown signal (for example, change SIGUSR1 in the above code to SIGUSR2 in sigqueue(pid, SIGUSR1, value);), and the binding function is not performed, the running result is as follows, the child process does not know Do anything and you'll get stuck

Compile again in linux

At this point, check that the process state is Z+ (zombie state - the child process ends before the parent process. There is an infinite loop in the child process, which should not end first, but because the child process receives an unknown signal, it will be interrupted , the child process is stuck there, that is, the original thing does not do, and it does not know what to do next, it enters the zombie state, occupies resources, and should be avoided)

4. When I only have one process, use kill to send a signal to him in linux

 The process receives an unknown signal (signal No. 10), prints out the user-defined signal 1, checks the process status, and finds that the pid cannot be found, that is, it is interrupted and destroyed, as if it played the role of killing the process (the previous The parent process sends an unknown signal to the child process, but it just gets stuck). So to ensure the normal execution of the process, you need to use signal shielding
 

Small scale chopper

 

Please indicate the source when loading

Cross-platform (Linux) development based on VS2019 C++ (1.4.2) - with parameter signals

The learning signal mask is as follows

https://blog.csdn.net/hml111666/article/details/123683046

Guess you like

Origin blog.csdn.net/hml111666/article/details/123564522