Under Linux, two child processes communicate through pipe s and receive the signal of the parent process to stop (complete code)

Posted by woolyg on Sat, 19 Feb 2022 15:09:52 +0100

Title Description:

Algorithm design:

Multi process:

Here we mainly use the system call fork:

  • fork is a system call to create a process under Linux
    The process calling fork is the main process, and a call will produce a child process.
  • fork features: call twice and return:
    The difference between the main process and the child process starts with the statement fork. The return value of fork to the calling main process is the PID of the child process (if successful), and the return value to the child process is 0. Therefore, it can be used to judge whether the current process is a child process or a parent process, such as:
int pid = fork();
if(pid==0){
//The description is a sub process. The related operations of the sub process are written here
}
else{
//The description is the parent process. The related operations of the parent process are written here
}

How to create multiple sub processes?
Wrong method:

for(int i=0;i<10:i++)
	fork();

This is obviously incorrect, because not only the parent process can execute the fork() statement, but also the child process, which will cause more processes to be created than expected, because there are child processes similar to the child process.
It's also very simple to avoid this problem. It's only necessary for the parent process to execute fork(). The method to distinguish the parent process from the child process has been given above.
My specific implementation code:

int childpid[10];//PID used to save all processes. No. 0 is the main process
childpid[0]=getpid();//012 is the pid of the parent process and two child processes respectively
for(int i=1;i<=2;i++){
		int pid=fork();
		if(pid!=0)
			childpid[i] =pid;
		else{
			childpid[i] =getpid();
			break;
		}
	}

Signaling mechanism:

Several functions are needed here:

		signal(SIGINT,SIG_IGN);

		signal(SIGUSR1,fun_chid);
		signal(SIGUSR2,fun_chid);
		
		kill(childpid[1],SIGUSR1);
		kill(childpid[2],SIGUSR2);

Signal is a simulation of interrupt mechanism at the software level. It is an asynchronous communication mode
When using the signal() function to process, you only need to indicate the signal to be processed and the processing function.
Prototype: / signal handler / * signal (int SIG, / signal handler / * handler);
Parameters:
sig: the signal to set the signal processing function. It can be an implementation defined value or a predefined macro:
handler: signal processing function. This must be one of the following:
SIG_DFL macro. The signal processing function is set as the default signal processing function.
SIG_IGN macro. Ignore the signal.
Pointer to the function.
Return value
Previous signal processing function in case of success and SIG in case of failure_ Err (some implementations can disable setting signal processing functions).
Signal:
SIGINT: ctrl+c termination signal
SIGQUIT: ctrl + \ termination signal
SIGTSTP:ctrl+z pause signal
SIGALRM: alarm signal. After receiving this signal, it will end at a fixed time and end the process
SIGCHLD: the state of the child process changes and the parent process receives the signal
SIGKILL: kill signal
  
Response mode of user process to signal:
Ignore signal
Capture signal
Perform default actions

Correlation function:
int kill(pid_t pid, int sig);
Function: signal transmission
Parameter: pid: specify process
sig: signal to be sent
Return value: success 0; Failed - 1

Pipeline communication:

	int flg,fd[2];
	flg = pipe(fd); //Create pipe
    if (flg == -1)
        perror("pipe error");

	
	write(fd[1],child,strlen(child)+1);
	read(fd[0],msg,sizeof(msg))
  • Prototype of pipe function:
    int pipe (int fd[2]); // 0 is returned for success and - 1 for error
    fd parameter is an array / pointer, which can bring back two values (file descriptor),
    fd[0] points to the read end of the pipe, and fd[1] points to the write end of the pipe. The output of fd[1] is the input of fd[0].

  • Process of pipe communication (between parent and child processes):
    1. The parent process creates a pipeline and gets two piece descriptors pointing to both ends of the pipeline
    2. The sending process closes fd[1] (reading end) and writes to the pipeline with write()
    3. Close fd[0] (write end) in the receiving process, and use read() to read from the pipeline

Implementation code:

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


int childpid[10]={-1,-1,-1,-1},status=999;

    

void fun_pare(int sig)//Parent process response Ctrl C signal function
{
	kill(childpid[1],SIGUSR1);
	kill(childpid[2],SIGUSR2);
}
void fun_chid(int sig)//Subprocess 1 response signal function
{
	if(sig==SIGUSR1)
		printf("\nChild Process 1 is killed by parent!\n");
	if(sig==SIGUSR2)
	printf("\nChild Process 2 is killed by parent!\n");
		
	exit(822);//Default normal exit return 0
}


int main(){

	int ret,fd[2];
	ret = pipe(fd); //Create pipe
    if (ret == -1)
        perror("pipe error");

	
	

	childpid[0]=getpid();//012 is the pid of the parent process and two child processes respectively

	for(int i=1;i<=2;i++){
		int pid=fork();
		if(pid!=0)
			childpid[i] =pid;
		else{
			childpid[i] =getpid();
			break;
		}
	}


		

	if(getpid()==childpid[0]){//Parent process
		printf("I am the parent process,PID:%d PPID:%d\n",getpid(),getppid());
		printf("\t Subprocess 1 is: PID:%d\n",childpid[1]);
		printf("\t Subprocess 2 is: PID:%d\n",childpid[2]);

		signal(SIGINT,fun_pare);//Send interrupt signal
			
		int child_num = 2;//Number of child processes
		while(child_num --){
		int t = wait(&status);//Wait for the two subprocesses to finish
		printf("A process is over, his PID:%d Return code :%d\n",t,status);
		}
		

		printf("Parent process is killed!\n");//The main process can end only after both sub processes are completed
		exit(822);//Default normal exit return 0
	}
	else{//Otherwise, it is a child process
		signal(SIGINT,SIG_IGN);
		signal(SIGUSR1,fun_chid);
		signal(SIGUSR2,fun_chid);
	}


	if(getpid()==childpid[1]){//Subprocess 1
		int i=0;
        close(fd[0]);
        char child[100]="I send message x times !\0";
		
        while(++i)
        {
			child[15] = '0' + i;
            write(fd[1],child,strlen(child)+1);
            sleep(1);
        }
	}
	if(getpid()==childpid[2]){//Subprocess 2
	 	close(fd[1]);
        char msg[100];
        while(1)
        {
            if(read(fd[0],msg,sizeof(msg)))
            	printf("%s\n",msg);
        }
	}	
	return 0;
}

Operation screenshot:

Topics: Linux multiple processes