linux入门:进程间通信之匿名管道

来源:互联网 发布:软件开发技术培训 编辑:程序博客网 时间:2024/05/17 17:18

  每个进程各自有不同的地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓 冲区,进程2再从内核缓冲区把数据读,内核提供的这种机制称为进程间通信。

      管道(匿名管道)是一种最基本的IPC机制,由pipe函数创建。

1. 父进程调 用pipe开辟管道,得到两个文件描述符指向管道的两端。
2. 父进程调 用fork创建 子进程,那么子进程也有两个文件描述符指向同 一管道。
3.  父进程关闭管道读端, 子进程关闭管道写端。父进程可以往管道写, 子进程可以管道里读,管道是用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通信。


匿名管道实现进程间通信有以下四种情况:
1.指向管道写端的文件描述符未关闭,持有管道写端的进程也未向管道中写入数据,这时有进程从管道读端读数据,那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才会读取数据并返回。

代码:


结果:



2.如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数等于0), 而仍然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就像读到 文件末尾 一样。

代码:


结果:



3.所有指向管道读端的文件描述符都关闭了,只是有进程向管道的写端write,那么该进程会受到信号SIGPIPE,通常会导致进程异常终止。

代码:


结果:



4.指向管道读端的文件描述符未关闭,而持有管道读端的进程也没有从管道中读取数据,这时有进程向管道写端写数据,那么当管道被写满时,再次write会阻塞,直到管道中有空位置了才再写入数据并返回。(类似情况1)


源代码:

#include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>int main(){int mypipefd[2];int fd = pipe(mypipefd);   //创建管道if(fd < 0)    //管道创建失败{perror("pipe");return 2;}pid_t id = fork();    //创建子进程if(id < 0){perror("fork");return 2;}else if(id == 0){close(mypipefd[0]);  //关闭子进程的读功能int i = 0;char *msg = NULL;while(i < 10){msg = "hello bit";write(mypipefd[1],msg,strlen(msg)+1);  //子进程写sleep(1);i++;}close(mypipefd[1]);   //发送完毕子进程关闭写功能exit(1);}else{close(mypipefd[1]);    //父进程关闭写功能char _msg[128];int j = 0;while(j < 10){ssize_t _s = read(mypipefd[0],_msg,sizeof(_msg)-1);//父进程读if(_s > 0){_msg[_s] = '\0';printf("child->father: %s\n",_msg);}else if(_s == 0)  //读到了文件结尾(指向管道写端的文件描述符关闭) //仍然有进程从管道的读端读数据,管道中剩余数据被读完则返回0{printf("pipe write is close\n");break;}j++;}close(mypipefd[0]);   //读完毕父进程关闭读功能int status = 0;pid_t ret = waitpid(id,&status,0);   if(ret < 0){perror("wait");}else{printf("exit code: %d, signal: %d\n",(status>>8)&0xff, status&0xff);}}}






0 0
原创粉丝点击