[linux interprocess communication] 1 signal

1, What is interprocess communication

1. A process is an independent resource allocation unit. Resources between different processes (user processes) are independent and have no association. Resources of other processes cannot be accessed in another process. In fact, different processes often need to interact to transfer state and other information, so inter process communication is needed.

2. Interprocess communication function:

Data transfer: one process needs to send its data to another process.

Resource sharing: multiple processes share the same resources.

Notification event: a process needs to send a message to another process or group of processes to notify them of an event.

Process control: some processes want to fully control the execution of another process (such as the Debug process). At this time, the control process wants to be able to intercept all operations of another process and know its state changes in time.

 3. The essence of interprocess communication: as long as the system creates a process, it will allocate 4G of virtual memory (32 bits) to the current process. Virtual memory is not the space of memory module (physical space), and there is a mapping relationship between virtual memory and physical memory

4G virtual memory is divided into 3G user space (0~3G) and 1g (3 ~ 4G) kernel space. The user space is private to the process. The user space of each process can only be accessed and used by itself. The stack area, heap area, data area and code area we mentioned earlier are all areas of user space

Kernel space is public to all processes, which means that most inter process communication methods are essentially the operation of kernel space

4.

socket communication can realize inter process communication between different hosts, and the other six can only communicate among multiple processes of one host

Signal communication is the only asynchronous communication mechanism

Shared memory is the most efficient of all interprocess communication methods. It operates directly on physical memory

2, Signal

1. Signal is software interrupt, which is a simulation of interrupt mechanism at the software level. Signals can cause a running process to be interrupted by another running asynchronous process to deal with an emergency. Signal is an asynchronous communication mode.

The process does not have to wait for the signal to arrive, and the process does not know when the signal will arrive. The signal can directly interact with the user space process and the kernel space process, and the kernel process can use it to inform the user space process of what system events have occurred.

2. The name of each signal begins with the character SIG. Each signal corresponds to a digital code in the header file Signum H, these signals are defined as positive integers. Signal name definition path:

          /usr/include/x86_64-linux-gnu/bits/signum.h

        /usr/include/x86_64-linux-gnu/bits/signum-generic.h

3. In linux, you can use kill -l to view the relationship between all signals and numbers

4. Signals are some identifications defined by the current system. Each identification will be used in specific occasions and will have a certain impact on the process. When the signal is generated, it will make the current signal do corresponding operations

5. Signal generation method

5.1 some terminal keys send signals

5.2 abnormal hardware will generate signals

5.3 signal generated by software abnormality

5.4 running the kill Command will generate a signal

5.5 call kill function to send signal

6. Signal processing mode

6.1 when a signal is generated in the process, the current process will respond to it. The default processing method is as follows (one of them):

  • Terminate process: when the signal is generated, the current process will end immediately
  • Default processing: when the signal is generated, the current process does not do any processing
  • Stop process: when the signal is generated, the current process is stopped
  • Let the stopped process resume running: when the signal is generated, the stopped process will resume execution (background process)

6.2 processing method after the process receives the signal

  • Perform the default operation in 6.1 above
  • Ignore the signal
  • Execute custom signal processing functions

Note: SIGKILL and SIGSTOP signals can only be processed by default and cannot be ignored or customized

6.3 common signals

signalvaluenatureDefault processing method
SIGKILL9When this signal is generated, the current process will exit and cannot be defaulted and capturedExit process
SIGSTOP19When this signal is generated, the current process will stop and cannot be defaulted and capturedStop process
SIGINT2A signal is generated when ctrl+c is entered on the keyboardExit process
SIGQUIT3A signal is generated when the keyboard inputs ctrl + \Exit process
SIGTSTP20A signal is generated when the keyboard inputs ctrl+zStop process
SIGCONT18When the current signal is generated, the currently stopped process will resume operationThe stopped process resumes operation
SIGALRM14When the time set by calling the alarm function arrives, the current signal will be generatedExit process
SIGPIPE13When the pipeline breaks, the current signal will be generatedExit process
SIGABRT6The current signal is generated when the abort function is calledExit process
SIGCHLD17When using fork to create a child process, if the child process state changes (exits), the current signal will be generateddefault
SIGUSR110The user-defined signal will not be generated automatically. You can only use the kill function or command to send the current signal to the specified processdefault
SIGUSR212The user-defined signal will not be generated automatically. You can only use the kill function or command to send the current signal to the specified processdefault

6.4 kill function

      #include <sys/types.h>
      #include <signal.h>

      int kill(pid_t pid, int sig);

6.4.1 function: send signal to the formulation process

6.4.2 parameters:

pid:

pid > 0: send the signal to the process with process ID pid.

pid=0: send the signal to all processes in the process group where the current process is located.

pid=-1: send the signal to all processes in the system.

pid < - 1: sends a signal to all processes in the specified process group. The process group number is equal to the absolute value of pid.

signum: number of signal

6.4.3 return value: success 0 failure - 1

6.4.4 examples

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
int main(){
	pid_t pid = fork();
	if(pid<0){
		perror("file  to fork");
		return -1;
	}
	if(pid==0){

		printf("*-son process-*\n");
		sleep(2);
		kill(getppid(),SIGKILL);
	}
	else{
		for(int i = 0;i<5;i++){
			printf("-****parent***-\n");
			sleep(1);
		}
	}
	return 0;
}

6.4.5kill command usage

kill - signal number process number

6.5 alarm function

       #include <unistd.h>

       unsigned int alarm(unsigned int seconds);

6.5.1 function: after the seconds arrive, send a SIGALARM signal to the calling process

6.5.2 parameter seconds: set the number of seconds

6.5.3 return value:

If the previous alarm function has no alarm setting, it returns 0

If yes, the remaining time of the previous alarm will be returned

6.5.4 examples

        int sec;
		sec = alarm(5);
		printf("sec = %d\n",sec);//Here sec=0
		for(int i = 0;i<4;i++){
			printf("*-son process-*\n");
			sleep(1);
		}
		sec = alarm(3);
		printf("sec=%d\n",sec);//Where sec=1
/*****************************************************
*If the alarm is set before and the time is not up, the alarm time will be reset,
*The return value is the number of seconds left in the last alarm
****************************************************/

6.6.raise function

       #include <signal.h>

       int raise(int sig);

6.6.1 function: Send a signal to the calling process itself

6.6.2 parameter: signum signal number

6.6.3 return value: success 0 failure - 1

6.6.4raise(sig)<==>kill(getpid(),sig)

6.6.5 it's so simple that we don't put examples

6.7 abort function

#include <stdlib.h>
void abort(void);

6.7.1 function: Send a SIGABRT signal to the process, and the process will exit by default

6.7.2 precautions: when SIGABRT signal is added to the blocking set, once the process calls abort function, the process will still be terminated, and the buffer will be refreshed and the file descriptor will be closed before termination

6.7.3 calling method: add abort() directly to the code; It's over

6.8 pause function

#include <unistd.h>
int pause(void);

6.8.1 function: suspend the calling process until the signal position is captured. This function is often used to judge whether the signal is received

6.8.2 return value: until the capture signal pause returns - 1 and ERRNO is EINTR

6.8.3 examples

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
int main(){
	pid_t pid = fork();
	if(pid<0){
		perror("file  to fork");
		return -1;
	}
	if(pid==0){
		for(int i = 0;i<4;i++){
			printf("*-son process-*\n");
			sleep(1);
		}
		kill(getppid(),SIGINT);
	}
	else{
			printf("-****parent***-\n");
			pause();
	}
	return 0;
}

6.9signal function

#include <signal.h>

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);

6.9.1 function: set the processing function for the signal, which is equivalent to the interrupt processing function in the interrupt

6.9.2 parameters

signum: signal number

        handler:

Ignore signal: SIG_IGN

Execution default: SIG_DFL

Custom processing function: function entry address (function name)

6.9.3 return value:

Success: return the function address, which is the address of the last registered signal processing function

Failed: return SIG_ERR

6.9.4 examples

Note the notes in the example

/********************************
*This routine mainly demonstrates the use of signal in inter process communication
*And how to use custom signal processing functions
*If you do not customize the second parameter, you can directly substitute the other two macros
*This is not demonstrated here
********************************/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

void func1(int sig){	//The return value of the signal processing function is null, and the parameter sig is the signal value of the received signal
	if(sig == SIGUSR1)        //After judgment, multiple signals can be processed with the same signal processing function
		printf("-*****using sigusr1****-\n");
	else
		printf("-******no sigusr1******-\n");
}
int main(){
	pid_t pid = fork();
	if(pid<0){
		perror("fail  to fork");
		return -1;
	}
	if(signal(SIGUSR1,func1)==SIG_ERR){//Register signal processing function
		perror("fail to signal");
		return -1;
	}

	if(pid==0){
		pause();//Suspend waiting for signal from parent process
		for(int i = 0;i<3;i++){
			printf("*-son process-*\n");
			sleep(1);
		}
		kill(getppid(),SIGUSR1);//Send signal to parent process
		sleep(2);
		exit(2);
	}
	else{
		printf("-****parent***-\n");
		sleep(1);//Sleep for one second here is to wait to ensure that the child process has been suspended and waiting for the signal,
                //Then send the signal
		kill(pid,SIGUSR1);//Send signals to child processes
		pause();//Hang
		printf("-*****parent****-\n");
		wait(NULL);//Wait for the child process to exit
	}
	return 0;
}

/********************************
*This routine mainly demonstrates the application of signal return value
********************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

void *handler;
void func1(int sig){	
	if(sig == SIGINT){
		if(signal(SIGINT,handler)==SIG_ERR){
			perror("fail to signal");
			exit(3);
		}
		printf("-************************-\n");
		printf("-*****using sigusr1****-\n");
		printf("-************************-\n");
		sleep(1);
	}
	else
		printf("-******no sigusr1******-\n");
}
int main(){
	if((handler = signal(SIGINT,func1))==SIG_ERR){
		perror("fail to signal");
		return -1;
	}
	while(1){
		printf("*-----main------*\n");
		sleep(1);
	}
	return 0;
}

3, Reentrant function

Reentrant functions are functions that can be used concurrently by multiple tasks without worrying about data errors

Reentrant function is a function that can be interrupted. The current function can interrupt it at any time and execute another piece of code. After execution, it can return to the original code and execute normally.

Notes for writing reentrant functions:

  1. Do not use (return) static data, global variables.
  2. Do not call functions that dynamically allocate memory and release memory
  3. Do not call any non reentrant functions (such as standard io functions)

When entering the processing function, first save the value of errno and restore the original value at the end.

Common reentrant functions

After being interrupted by the signal, the application can return to the original position of the function and continue to execute

4, Signal set

1. A user process often needs to process multiple signals. In order to facilitate the processing of multiple signals, a signal set is introduced into linux system. The signal set is used to represent the data type of multiple signals

2. Data type of signal set sigset_t

3. Signal set operation function

3.1 sigemptyset function

#include <signal.h>
int sigemptyset(sigset_t *set);

Function: initialize the signal set pointed to by set and clear all signals therein

Parameter: Set: address of signal set identification

Return value: success 0 failure - 1

3.2 sigfillset function

#include<signal.h>
int sigfillset(sigset_t *set);

Function: initialize the signal set and set the signal set as the set of all signals

The return value of the parameter is the same as above

3.3 sigismember function

#incldue <signal.h>
int sigismember(const sigset_t *set,int signum);

Function: query whether the signal represented by signum is in the signal set

Parameter: signum: signal number

Return value: returns 1 if found, 0 if not found, and - 1 if error

3.4sigaddset function

#include <signal.h>
int sigaddset(sigset_t *set,int signum);

Function: add the signal indicated by signum to the signal set

Return value: success 0 failure - 1

3.5 sigdelset function

#include <signal.h>
int sigdelset(sigset_t *set,int signum);

Function: delete the signal indicated by signum from the signal set

Return value: success 0 failure - 1

5, Signal blocking set

1. Each process has a blocking set, which is used to describe those signals that are blocked when they are delivered to the process (remember it when the signal occurs, and notify the process of the signal until the process is ready). The so-called blocking is not to prohibit the transmission of signals, but to suspend the transmission of signals. If the blocked signals are deleted from the signal blocking set and the corresponding signals occur when they are blocked, the process will receive the corresponding signals.

2. Correlation function of signal blocking set: sigprocmask function

#include <signal.h>
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);

Function: check or modify the signal blocking set, and modify the blocking set and of the process according to the method specified by how. The new signal blocking set is specified by set, while the original signal blocking set is saved by oldset

Parameters:

how: modification method of signal blocking set. The optional parameters are as follows:

                SIG_BLOCK: adds a set signal set to the signal block set

                SIG_UNBLOCK: deletes the set signal set from the signal blocking set

                SIG_SETMASK: set the signal blocking set to set

Set: address of the signal set to be operated

oldset: save the address of the original signal blocking set

Return value: 0 for success and - 1 for failure

 3. example

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int main(){
	sigset_t myset;
	sigemptyset(&myset);
	sigaddset(&myset,SIGINT);
	
	sigprocmask(SIG_BLOCK,&myset,NULL);

	for(int i = 0;i<5;i++)
	{
		printf("hello world!\n");
		sleep(1);
	}
	/************************************************************
    *If you ctrl+c for the first 5 seconds, the printing will not be interrupted immediately, and the signal will be removed from the blocking set after 5 seconds
    *The previously blocked signal will be processed immediately, so the process will exit immediately
    *************************************************************/
	sigprocmask(SIG_UNBLOCK,&myset,NULL);
	for(int i = 0;i<5;i++){
		printf("hello unblock!\n");
		sleep(1);
	}
    /************************************************************
    *After 5 seconds, ctrl+c will stop the process. At this time, the SIGINT signal has moved out of the blocking set
    *************************************************************/
	return 0;
}

Keywords: Linux

Added by thomasgrant on Mon, 03 Jan 2022 01:23:16 +0200