进程间通信的总结之管道

无名管道

管道是Linux支持的最早的Unix IPC形式之一,具有以下特点:

  管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;

  只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);

  单独构成一种独立的文件系统;管道对于管道两端的进程而言,就是一个文件,但不是一个普通的文件,它不属于某种文件系统,而死自立门户,单独构成一种文件系统,存在于内存之中;

  数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <errno.h> main() { int pipe_fd[2]; pid_t pid; char r_buf[100]; char w_buf[4]; char* p_wbuf; int r_num; memset(r_buf,0,sizeof(r_buf)); memset(w_buf,0,sizeof(r_buf)); p_wbuf=w_buf; if(pipe(pipe_fd)<0) { printf("pipe create error\n"); return -1; } if((pid=fork())==0) { printf("\n"); close(pipe_fd[1]); sleep(3);//确保父进程关闭写端 r_num=read(pipe_fd[0],r_buf,100); printf( "read num is %d the data read from the pipe is %d\n",r_num,atoi(r_buf)); close(pipe_fd[0]); exit(); } else if(pid>0) { close(pipe_fd[0]);//read strcpy(w_buf,"111"); if(write(pipe_fd[1],w_buf,4)!=-1) printf("parent write over\n"); close(pipe_fd[1]);//write printf("parent close fd[1] over\n"); sleep(10); } }

向管道写入数据时要注意:linux不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走缓冲区的数据,那么写操作将一直阻塞。只有在管道的读端存在时,向管道中写入数据才有意义,否则,向管道中写入数据的进程将受到内核的SIPPIPE信号,应用程序默认终止。如下程序:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <sys/types.h> main() { int pipe_fd[2]; pid_t pid; char r_buf[4]; char* w_buf; int writenum; memset(r_buf,0,sizeof(r_buf)); if(pipe(pipe_fd)<0) { printf("pipe create error\n"); return -1; } if((pid=fork())==0) { close(pipe_fd[0]);// 注意 close(pipe_fd[1]); sleep(10); exit(); } else if(pid>0) { sleep(1); //等待子进程完成关闭读端的操作 close(pipe_fd[0]);//write w_buf="111"; if((writenum=write(pipe_fd[1],w_buf,4))==-1) printf("write to pipe error\n"); else printf("the bytes write to pipe is %d \n", writenum); close(pipe_fd[1]); } }

以上程序将不会执行,因为子进程将读管道关闭了,而父进程往管道里面写的话,将受到系统内核发送的终止信号而结束。如果你在父进程中将close(pipe_fd[0])打开,那么写入操作将会成功。

另外注意的一点是管道操作的写入操作不保证写入的原子性,管道中只要一有空间就将进行写入操作。(对并发写入操作的时候要注意当写入的数据量大于PIPE_BUF的时候,系统将不保证写入的原子性,这样可能读出的数据出现混乱。) 

还有一个缺点是管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息。

原文地址:https://www.cnblogs.com/fxplove/p/2676434.html