IPC:管道之协同进程

参考https://blog.csdn.net/u014325402/article/details/78992786

在shell 管道中,当一个程序产生一个过滤器的输入,又读取这个过滤器的输出,则此种过滤程序叫做协同进程.
协同进程通常在shell的后台运行,其标准输入和标准输出通过管道连接到另一个程序。
popen 与协同进程的区别:
popen只提供连接到另一个进程的标准输入或标准输出的一个单向管道;
协同进程,连接到另一个进程的两个单向管道:一个接到其标准输入,另一个则来自其标准输出;

协同进程演示: 创建两个管道, 一个是协同进程的标准输入,另一个是协同进程的标准输出,将数据写到其标准输入,经其处理后,再从其标准输出读取数据。

协同进程演示: 创建两个管道, 一个是协同进程的标准输入,另一个是协同进程的标准输出,将数据写到其标准输入,经其处理后,再从其标准输出读取数据。

这里写图片描述

第一步, 创建两个管道,fd1[2]和fd2[2](父进程在fd1[1]写入数据,再从fd2[0]读出数据)。
第二步, 调用fork()创建子进程。
第三步, 在子进程中,关闭fd1[1], fd2[0],并调用dup2使协同进程的标准输入连接到fd1[0], 标准输出连接到fd2[1],这样就将两个管道连接起来了。
再在子进程中调用execl调用编写的协同处理程序(这里的协同程序做为一般的程序编写即可,从标准输入读入数据,处理后输出到标准输出)。
第四步, 在父进程中,关闭fd1[0], fd2[1],将协同进程需要处理的数据写入fd1[1], 再从fd2[0]读出协同进程的输出即可。
apue.e3程序清单15-8 对两个数求和的简单过滤程序:一个简单的协同进程,它从其标准输入读两个数,计算它们的和,然后将结果写至标准输出。

#include "apue.h"

static void	sig_pipe(int);		/* our signal handler */

int
main(void)
{
	int		n, fd1[2], fd2[2];
	pid_t	pid;
	char	line[MAXLINE];

	if (signal(SIGPIPE, sig_pipe) == SIG_ERR)
		err_sys("signal error");

	if (pipe(fd1) < 0 || pipe(fd2) < 0)
		err_sys("pipe error");

	if ((pid = fork()) < 0) {
		err_sys("fork error");
	} else if (pid > 0) {						/* parent */
		close(fd1[0]);
		close(fd2[1]);

		while (fgets(line, MAXLINE, stdin) != NULL) {
			n = strlen(line);
			if (write(fd1[1], line, n) != n)
				err_sys("write error to pipe");
			if ((n = read(fd2[0], line, MAXLINE)) < 0)
				err_sys("read error from pipe");
			if (n == 0) {
				err_msg("child closed pipe");
				break;
			}
			line[n] = 0;	/* null terminate */
			if (fputs(line, stdout) == EOF)
				err_sys("fputs error");
		}

		if (ferror(stdin))
			err_sys("fgets error on stdin");
		exit(0);
	} else {						/* child */
		close(fd1[1]);
		close(fd2[0]);
		if (fd1[0] != STDIN_FILENO) {
			if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO)
				err_sys("dup2 error to stdin");
			close(fd1[0]);
//为何要关闭fd1[0]?因为dup2中已经将fd1[0]换成了STDIN,即已将stdin与fd1[1]相连接
		}

		if (fd2[1] != STDOUT_FILENO) {
			if (dup2(fd2[1], STDOUT_FILENO) != STDOUT_FILENO)
				err_sys("dup2 error to stdout");
			close(fd2[1]);//同上
		}
		if (execl("./add2", "add2", (char *)0) < 0)
			err_sys("execl error");
	}
	exit(0);
}

static void
sig_pipe(int signo)
{
	printf("SIGPIPE caught\n");
	exit(1);
}

add2的程序见apue

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值