进程间通信————管道

来源:互联网 发布:18亿亩耕地红线知乎 编辑:程序博客网 时间:2024/06/01 23:26

进程间通信
首先,每个进程有各自不同的地址空间,任何一个进程都不能看到别的进程的系统资源。因此,进程间通信的主要方式是通过内核,首先在内核中开辟出一个缓冲区。把进程1的要沟通的数据写到缓冲区中去,然后通过进程2读走缓冲区的内容,这样才实现了进程间的通信(IPC)。
这里写图片描述
一、匿名管道
1.管道是一种简单的进程间通信方法,有IPC机制。通过调用pipe函数在内核中创建出缓冲区(管道)
#include < unistd.h >
int pipe(int filedes[2]);

通过输出型参数传出文件描述符(以前的文章介绍过)。其中filedes[0]指向读端,filedse[1]指向写端。
就如同打开一个文件一样。成功返回0,失败返回-1。
2.匿名管道的通信步骤:
通过父进程调用pipe创建管道,得到两个文件描述符指向管道,在fork()出子进程,子进程也有两个文件描述符共同指向管道。关闭相应的文件描述符读写端,就可以进行通讯。
这里写图片描述

#include<stdio.h>#include<error.h>#include<unistd.h>#include<string.h>int main(){    int fd[2];    int ret=pipe(fd);    if(ret==-1)    {        perror("pipe");        return -1;    }    pid_t id=fork();    if(id<0)    {    perror("fork");    return 1;    }    else if(id==0)    {        //child        close(fd[0]);//close read        int i=0;        char *str=NULL;        while(i<10)        {            str="i am your child";            write(fd[1],str,strlen(str)+1);            sleep(1);            i++;        }    }    else{    //father     close(fd[1]);//close write     char msg[100];     int j=0;     printf("father:\n");     while(j<10)     {         memset(msg,'\0',sizeof(msg));         read(fd[0],msg,sizeof(msg));         printf("%s \n",msg);         j++;     }    }    return 0;}

运行结果:
父进程打印出消息。如果要进行父进程写入,子进程读只需要关闭子进程的写端,父进程的读端。
这里写图片描述
3.匿名管道的特点:
①.这种管道通信只适用于单向通信。
②.常常用于父子间的通信,而且一定要具有血缘关系,比如父子进程,爷孙进程,兄弟进程等等。
③.管道的生命周期,随着进程结束而结束。
④.管道通信,面向字节流的通信。
⑤.管道通信自带同步机制。
4.匿名管道的几种特殊情况:
①.写端写满后停滞,等待读端读。
②.写端一直不写,读端处于阻塞状态等待。
③.读端关闭,写端会被操作系统终止,(收到来自进程的SIGPIPE)。
④.写端停止,等待读端读取,最后关闭,返回0。
二、命名管道(FIFO)
匿名管道的一个不足之处在于它没有名称。因此诞生了命名管道,命名管道某种程度上可以看做是匿名管道,但是他可以进行非血缘关系进程间的通信。之所以能够这样,是因为它可以通过同一个路径名而看到同一份资源,这份资源以FIFO的文件形式存在于文件系统中。
管道的创建:

 #include< sys/types.h > #include< sys/stat.h > int mkfifo(const char * filename ,mode_t mod); int mkfifo(const char * filename ,mode_t mod |   S _IFIFO,(dev_t)0);


两个函数都是创建文件。
filename是文件名,mod是操作权限。因为创建文件在系统中,读写操作都是对文件的操作,对于匿名管道那种不可见的操作,这种做法更突出可见性。因为命名管道是一个文件,可以用于任何两个进程的通信。

原创粉丝点击