ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux下两个子进程通过管道(pipe)通信,接受父进程的信号(signal)停止(完整代码)

2021-04-30 13:00:35  阅读:273  来源: 互联网

标签:int signal pid pipe fd 进程 childpid


题目描述:

算法设计:

多进程:

这里主要是利用系统调用fork:

  • fork是Linux下创建进程的一个系统调用
    调用fork的进程为主进程,一次调用会产生一个子进程。
  • fork的特点:一次调用两次返回:
    主进程和子进程的差异就从fork这条语句开始,fork给调用他的主进程的返回值是子进程的PID (若成功),给子进程的返回值是0,故可由此判断当前进程是子进程还是父进程,如:
int pid = fork();
if(pid==0){
//说明是子进程,这里写子进程的相关操作
}
else{
//说明是父进程,这里写父进程的相关操作
}

如何创建多个子进程?
错误的方法:

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

这显然不正确,因为不仅有父进程可以执行fork()语句,子进程也能执行,这就会导致实际创建的进程比预期的要多,因为有类似子进程的子进程存在。
避免这个问题也很简单,只在父进程执行fork()就行了,区分父子进程的方法上面已经给出。
我的具体实现代码:

int childpid[10];//用来保存所有进程的PID,0号是主进程
childpid[0]=getpid();//012分别是父进程和两个子进程的pid
for(int i=1;i<=2;i++){
		int pid=fork();
		if(pid!=0)
			childpid[i] =pid;
		else{
			childpid[i] =getpid();
			break;
		}
	}

信号机制:

这里需要用到几个函数:

		signal(SIGINT,SIG_IGN);

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

信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式
使用signal()函数处理时,只需指出要处理的信号和处理函数即可。
原型:/signal-handler/* signal(int sig, /signal-handler/* handler);
参数:
sig:要设置信号处理函数的信号。它可以是实现定义值或预定义的宏:
handler:信号处理函数。这必须是下列之一:
SIG_DFL 宏。信号处理函数被设为默认信号处理函数。
SIG_IGN 宏。忽略信号。
指向函数指针。
返回值
成功时为先前的信号处理函数,失败时为 SIG_ERR (某些实现上能禁用设置信号处理函数)。
信号:
  SIGINT:ctrl+c 终止信号
  SIGQUIT:ctrl+\ 终止信号
  SIGTSTP:ctrl+z 暂停信号
  SIGALRM:闹钟信号 收到此信号后定时结束,结束进程
  SIGCHLD:子进程状态改变,父进程收到信号
  SIGKILL:杀死信号
  
用户进程对信号的响应方式:
忽略信号
捕捉信号
执行缺省操作

相关函数:
int kill(pid_t pid, int sig);
  功能:信号发送
  参数:pid:指定进程
  sig:要发送的信号
  返回值:成功 0;失败 -1

管道通信:

	int flg,fd[2];
	flg = pipe(fd); //创建管道
    if (flg == -1)
        perror("pipe error");

	
	write(fd[1],child,strlen(child)+1);
	read(fd[0],msg,sizeof(msg))
  • pipe函数的原型:
    int pipe (int fd[2]); //成功返回0,出错返回-1
    fd参数是数组/指针,可以带回两个值(文件描述符),
    fd[0]指向管道的读端,fd[1]指向管道的写端。fd[1]的输出是fd[0]的输入。

  • pipe通信(父子进程间)的流程:
    1.父进程创建管道,得到两个件描述符指向管道的两端
    2.发进程关闭fd[1](读端),利用write()向管道写入
    3.收进程关闭fd[0](写端),利用read()从管道读出

实现代码:


#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)//父进程响应Ctrl C 信号函数
{
	kill(childpid[1],SIGUSR1);
	kill(childpid[2],SIGUSR2);
}
void fun_chid(int sig)//子进程1响应信号函数
{
	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);//默认正常退出返回0
}


int main(){

	int ret,fd[2];
	ret = pipe(fd); //创建管道
    if (ret == -1)
        perror("pipe error");

	
	

	childpid[0]=getpid();//012分别是父进程和两个子进程的pid

	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]){//父进程
		printf("我是父进程,PID:%d PPID:%d\n",getpid(),getppid());
		printf("\t子进程1是:PID:%d\n",childpid[1]);
		printf("\t子进程2是:PID:%d\n",childpid[2]);

		signal(SIGINT,fun_pare);//发出中断信号
			
		int child_num = 2;//子进程个数
		while(child_num --){
		int t = wait(&status);//等待两个子进程结束
		printf("一个进程结束了,他的 PID:%d 返回码 :%d\n",t,status);
		}
		

		printf("Parent process is killed!\n");//两个子进程都结束后主进程才可以结束
		exit(822);//默认正常退出返回0
	}
	else{//否则是子进程
		signal(SIGINT,SIG_IGN);
		signal(SIGUSR1,fun_chid);
		signal(SIGUSR2,fun_chid);
	}


	if(getpid()==childpid[1]){//子进程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]){//子进程2
	 	close(fd[1]);
        char msg[100];
        while(1)
        {
            if(read(fd[0],msg,sizeof(msg)))
            	printf("%s\n",msg);
        }
	}	
	return 0;
}

运行截图:

在这里插入图片描述

标签:int,signal,pid,pipe,fd,进程,childpid
来源: https://blog.csdn.net/weixin_46291251/article/details/116274665

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有