首页 > 其他 > 详细

linux进程通信之管道

时间:2014-03-08 15:59:54      阅读:492      评论:0      收藏:0      [点我收藏+]

管道是UNIX系统IPC最古老的形式,并且所有UNIX系统都提供此种通信机制。管道有下面两种局限性。

1.历史上,它们是半双工的,数据只能在一个方向上流动

2只能在公共祖先的进程之间使用。例如,父子进程之间就可应用管道。

尽管有这两种局限性,半双工管道仍是最常用的IPC形式


管道是用pipe函数创建的

#include <unistd.h>

int pipe(int pipefd[2]);

返回值:若成功则返回0,若出错则返回-1

pipefd[0]为读而打开, pipefd[1]为写而打开


fstat函数对管道的每一端都返回一个FIFO类型的文件描述符,可以用S_ISFIFO宏来测试管道。详情见http://blog.csdn.net/aspnet_lyc/article/details/20716169

单个进程中管道几乎没有任何用处。通常,调用pipe的进程接着调用fork,这样就创建了从父进程到子进程的IPC管道。

bubuko.com,布布扣


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

main()
{
	int  fd[2];
	int  pid;
	char buf[1024];
	int  r;
	
	if (pipe(fd) < 0)
		printf("pipe error\n"), exit(-1);
	if ((pid = fork()) < 0)
		printf("fork error\n"), exit(-1);
	if (pid > 0) {
		close(fd[0]);
		write(fd[1], "Hello World\n", 12);	
	} else {
		close(fd[1]);
		r = read(fd[0], buf, 1024);
		write(STDOUT_FILENO, buf, r);	
	}
	exit(0);
}

输出结果为

Hello World


当管道的一端被关闭后,下列两条规则起作用:

1.读一个写端已被关闭的管道时,在所有数据都被读取后,read返回0,以指示达到了文件结束处。

如下程序将会阻塞,“子进程终止”并不会被打印出来,执行结果输出 Hello World

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

main()
{
	int  fd[2];
	int  pid;
	char buf[5];
	int  r;
	
	if (pipe(fd) < 0)
		printf("pipe error\n"), exit(-1);
	if ((pid = fork()) < 0)
		printf("fork error\n"), exit(-1);
	
	if (pid == 0) {           //子进程
		close(fd[1]);     //子进程关闭写

		while(1) {
			r = read(fd[0], buf, 5);
			if (r > 0) {
				buf[r] = 0;
				printf("%s", buf);
			}	
			else if (r == 0)
				break;
			else
				printf("此行不会被打印,因为读到结尾处read函数阻塞\n");
		}

		exit(0);	
	} else {		   //父进程
		close(fd[0]);      //父进程关闭读
		write(fd[1], "Hello World\n", 12);
		
		wait(0);
		printf("子进程终止\n");
		exit(0);
	}		
}

改进后的程序,父子进程都关闭写,写端被关闭,读端读到文件结尾read会返回0

执行结果

Hello World

子进程终止

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

main()
{
	int  fd[2];
	int  pid;
	char buf[5];
	int  r;
	
	if (pipe(fd) < 0)
		printf("pipe error\n"), exit(-1);
	if ((pid = fork()) < 0)
		printf("fork error\n"), exit(-1);
	
	if (pid == 0) {    
		close(fd[1]);  //子进程关闭写

		while(1) {
			r = read(fd[0], buf, 5);
			if (r > 0) {
				buf[r] = 0;
				printf("%s", buf);
			}	
			else if (r == 0)
				break;
			else
				printf("此行不会被打印,因为读到结尾处read函数阻塞\n");
		}

		exit(0);	
	} else {		   
		close(fd[0]);  
		write(fd[1], "Hello World\n", 12);
		close(fd[1]);  //父进程关闭写
		wait(0);
		printf("子进程终止\n");
		exit(0);
	}		
}

2.如写一个读端已被关闭的管道,则产生SIGPIPE信号,如果忽略该信号或捕获该信号并从其处理程序返回,则write返回-1,errno设置为EPIPE

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

main()
{
	int  fd[2];
	int  pid;
	char buf[5];
	int  r;
	
	if (pipe(fd) < 0)
		printf("pipe error\n"), exit(-1);
	if ((pid = fork()) < 0)
		printf("fork error\n"), exit(-1);
	
	if (pid == 0) {            //子进程
		close(fd[0]);      //子进程关闭读
		while(1) {
			r = write(fd[1], "Hello World\n", 12);
			if (r == -1)
				break;		
		}
		exit(0);	
	} else {		   //父进程
		close(fd[0]);      //父进程关闭读
		wait(0);
		printf("子进程终止\n");
		exit(0);
	}		
}


linux进程通信之管道,布布扣,bubuko.com

linux进程通信之管道

原文:http://blog.csdn.net/aspnet_lyc/article/details/20773121

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!