Linux inter-process communication ① - signal (Signal)

1. What is inter-process communication

1. Introduction to interprocess communication

The user space of the process is independent of each other and generally cannot access each other. The only exception is the shared memory area. The kernel space is shared by each process. Therefore, if you want to communicate between different processes, you need to pass the kernel To achieve, processes can exchange data and information with each other.

2. Types of interprocess communication

(1) Signal
(2) Pipeline ( Linux interprocess communication ②——pipe (pipe, fifo) )
(3) socket
(4) Semaphore ( Linux interprocess communication ③——Semaphore (Semaphore) )
(5 ) Shared memory ( Linux inter-process communication ④——Shared Memory (Shared Memory) )
(6) Message queue
This article mainly explains the use of signal communication, and the rest of the content will be introduced one by one later

2. Signal introduction

Signal is the only asynchronous communication mechanism in inter-process communication. It is an interrupt simulation at the software level. It can send a signal to a certain process at any time without knowing the status of the process. It is used to notify the receiving process that an event has been completed. occur.
Regardless of whether the process is in an unexecuted or blocked state, it will eventually be passed to the process when it returns to normal state. There are dozens of signals in Linux, which represent different meanings, and there are different processing methods for these signals.

① Execute the default operation: the processing of the signal retains the default value of the system. This default operation, the default operation for most signals is to make the process terminate, and the process specifies the process’s response to a certain signal through the system call signal Processing behavior
②Capture signal: You can define a processing function (installation signal) for the signal, and when the signal occurs, execute the corresponding processing function, similar to an interrupt handler ③Ignore signal: When you do not want to
process certain signals, you can ignore them This signal, do not do any processing

Under Linux, you can use kill -l to view the definitions of all signals. When using signals, you can use man 7 signal to view signal trigger conditions and their default processing actions.
insert image description here

1. Function introduction

(1)signal()

#include <signal.h>
typedef void (*sig_handle)(int);//信号处理函数
sighandler_t signal(int signum,sig_handle handle);

①Function function: set the signal processing function for the specified signal number;
②Function parameters: signum is the signal code to be processed, handle is the action associated with the signal, where SIG_IGN means ignore the signal, and SIG_DFL means restore the system for the signal Default processing, function pointer of sig_handle type, use the function to process the signal;
③ Function return value: success, return the previous signal processing function pointer; failure, return SIG_ERR (-1);

(2)kill()

#include <sys/types.h>
#include <signal.h>
int kill(pid_t,int signum);

①Function function: Send a specified signal to a specified process;
②Function parameters: pid>0, the process that sends the signal, pid = 0, the signal is sent to all processes that call kill() and belong to the same use group, pid = - 1. The signal is sent to all processes that the calling process has the right to send signals to, except the process (init), pid<-1, the signal is sent to the process identified by -pid as the group; signum is the signal code to be sent;
③Function return value: success returns 0, failure returns -1;

(3)wait()

#include <sys/types.h>
#include <sys/wait.h>
int	wait(int *wstatus);

If the parent process does not use the wait() function to wait for the terminated child process, the child process will be in the state of no parent process. At this time, the child process will become a zombie process and still occupy system resources. wait() needs to be combined with fork( ) appear together, and call wait() after fork(), wait() is similar to waitpid(), waitpid() can be found in the detailed explanation of Linux multi-process

①Function function: block and wait for the sub-process to exit, recycle the residual resources of the sub-process, and obtain the end status of the sub-process (exit reason); ②Function
parameters: the outgoing parameter wstatus/status is used to save the exit status of the process, and when it is NULL, it means ignored The state when the child process exits
③ Function return value: success, returns the recycled child process ID; failure, returns -1 (no child process);

2. Inter-process communication - signal

After the parent process creates a child process, there is no special regulation on the running order of the parent and child processes, which is determined by the process scheduling policy of the operating system, but signals can be used to achieve inter-process synchronization, which can ensure the running order of the parent and child processes.
The following program ensures that the child process executes before the parent process, and exits first after receiving the notification from the parent process. It can ensure that the parent process can recycle the child process to prevent it from becoming a zombie process, and then exits at the end.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

int   child_stop = 0;		//定义全局变量
int   parent_run = 0;

void sig_child(int signum)//信号处理函数1
{
    
    
    if(SIGUSR1 == signum)
    {
    
       
        child_stop = 1; 
    }   
}

void sig_parent(int signum)//信号处理函数2
{
    
    
    if(SIGUSR2 == signum)
    {
    
       
        parent_run = 1;
    }   
}

int main (int argc,char **argv)
{
    
    
    pid_t     pid;//定义进程号
    int       wstatus;//定义传出参数,用来保存进程退出状态
    signal(SIGUSR1,sig_child);//安装信号,用户自定义信号,当发送SIGUSR1则执行sig_child
    signal(SIGUSR2,sig_parent);
	pid = fork();
    if(pid < 0)
  {
    
    
        printf("create child process failure\n");
        return -1;
    }
    else if(pid == 0)//子进程运行
    {
    
    
        printf("child process start running and send signal to parent process\n");
        kill(getppid(),SIGUSR2);//子进程通过kill函数发送SIGUSR2的信号到父进程,则父进程可开始运行

        while(!child_stop)//未收到父进程传的信号则处于循环休眠等待
        {
    
    
            sleep(1);
        }
        printf("child process receive signal from parent process and exit now\n");//接收到SIGUSR1信号,则可退出
        return 0;
    }
    printf("parent hangs up untill receive signal from child!\n");//接收到子进程传送的SIGUSR2信号才可运行
    while(!parent_run)//等待子进程运行后,父进程才进行,确保了子进程先运行
    {
    
    
        sleep(1);
    }
    printf("parent process start running now and send child process signal to exit\n");
    kill(pid,SIGUSR1);		//父进程进行后发送SIGUSR1信号给子进程,使其退出循环

    wait(&wstatus);		//父进程等待子进程退出(若子进程退出父进程不收尾则会使其变为僵尸进程),未找到子进程会一直处于阻塞状态
    printf("parent wait child process die and exit now.\n");
    return 0;
}

Guess you like

Origin blog.csdn.net/xll102500/article/details/129422486