我们都知道,进程的运行具有独立性,那么如果想让进程之间通信,该如何实现呢?今天我们就来看几种进程间通信(IPC)。
说到进程间的通信,它的本质就让不同的进程看到同一块资源,这也是进程间通信的前提。
一、管道
进程间通信最基本的机制:管道–>由pipe创建
#include <unistd.h>
int pipe(int filedes[2]);
调用pipe函数时在内核中开辟一块缓冲区(管道)用于通信
其中参数filedes[2]是两个文件描述符,一个是管道的读端,一个是管道的写端,所以管道在用户程序看起来就像一个打开的文件,通过read(filedes[0]);或者write(filedes[1])
返回值:pipe函数的调用,如果,成功,那么返回0,失败返回-1
管道的特性:
1、只能实现单向通信
2、只能只能用于有血缘关系的进程之间,通常用于父子之间
3、内部自带同步机制(进程的读或写的一方停止,但是没有关闭,那么另一会继续写或读,直到将管道写满,或是读空为止,这时,会等待)
4、对外部的服务:面向字节流的服务(读或写的时候,对数据没有明确的格式要求)
5、管道在进程退出时也随之退出(随进程)
创建管道的步骤:
1、父进创建管道,得到两个文件描述符
2、父进程创建子进程,则子进程也有两个文件描述符指向同一个管道
3、父进程关闭管道的读端,子进程关闭管道的写端;父进程朝管道里写内容,子进程读取这些内容。
如图所示:
代码实现:
思考:如果开辟一个管道,父进程不关闭管道的读端,子进程也不关闭管道的写端,双方都有读写端,为什么不能实现双向通信?
二、命名管道
上面我们说的都是匿名管道,接下来来看一下命名管道,其实这和管道的特点基本保持一致,唯一的区别是:命名管道可以用于非血缘关系进程之间
代码:
server.c
client.c
结果显示:
管道看完了,那么管道到底有多大呢?
我们来测试一下,创建一个管道,然后只写,看看什么时候满就行了
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<stdlib.h>
4
5 int main(int argc,char* argv[])
6 {
7 int _pipe[2];
8 pipe(_pipe);
9
10 char buf[4096];//a page
11 int j=0;
12 for(j=0;j<sizeof(buf);j++)
13 {
14 buf[j]=0x7f;
15 }
16
17 ssize_t ret=-1;
18
19 int loop=100;
20 if(argc>1)
21 {
22 loop=atoi(argv[1]);
23 }
24 int i=0;
25 for(i=0;i<loop;i++)
26 {
27 printf("loop;%d\n",i);
28 ret=write(_pipe[1],buf,sizeof(buf));
29 if(ret<0)
30 {
31 perror("write");
32 }
33 else
34 {
35 printf("%d\n",ret);
36 }
37 }
38 close(_pipe[0]);
39 close(_pipe[1]);
40 return 0;
41 }
我们可以看到,管道的大小:16*4096=64K