
Linux——进程间通信
进程通讯的目的
- 进行数据传输,将一个进程的数据发送给另一个进程。
- 多个进程之间共享资源。
- 通知事件:一个进程需要向另一个进程发送消息。(如子进程终止时通知父进程)
- 进程控制:有些进程希望完全控制另一个进程的执行。
进程通信的方式:
- 管道
- System V进程间通信
- POSIX进程间通信
1.管道
管道是Unix中的一种最古老的的进程见得通信方式,它是一个进程连接到另一个进程的数据流。使用的方式是标准输出和标准输入。
匿名管道
创建一个管道:
int pipe(int,fd[2]);
//fd为文件描述符数组,fd[0]代表读端,fd[1]代表写端
//返回0时代表成功,失败时返回错误码
从键盘读取数据,写入管道,读取管道,写到屏幕:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main( void )
{
int fds[2];
char buf[100];
int len;
if ( pipe(fds) == -1 )
perror("make pipe"),exit(1);
// 从标准输入中读数据(键盘)
while ( fgets(buf, 100, stdin) ) {
len = strlen(buf);
// 将数据写入管道
if ( write(fds[1], buf, len) != len ) {
perror("write to pipe");
break;
}
memset(buf, 0x00, sizeof(buf));
// 从管道读取数据
if ( (len=read(fds[0], buf, 100)) == -1 ) {
perror("read from pipe");
break;
}
// 将读取到的数据写入标准输出(屏幕)
if ( write(1, buf, len) != len ) {
perror("write to stdout");
break;
}
}
return 0;
}
从上面的代码不难看出, 管道的操作类似于文件操作. Linux下一切皆文件的思想得以在此体现.
管道特点
- 只能用于具有共同祖先的进程(具有亲缘关系的进程)之间的通信. 一般由一个进程创建管道, 然后调用fork, 父子进程就可以应用这个管道.
- 管道的生命周期和进程一致.
- 内核会对管道操作进行互斥\
- 管道是半双工通信, 数据只能朝一个方向流动, 需要互相通信时, 需要建立两个管道.
命名管道
命名管道可以从命令行上进行创建:
mkfifo filename
2.system V共享
我们在学习内存分配的时候一定会看见这样一张图:
中间的共享区, 大家在学的时候都比较懵逼这是干啥的.
这就是进程间通讯的第二种方式——共享内存需要使用到的区域.
共享内存是最快的IPC形式. 一旦这样的内存映射到共享它的进程的地址空间, 这些进程间数据传递不再涉及到内核, 换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据.
进程互斥
- 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥.
- 系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源.
- 在进程中涉及到互斥资源的程序段叫临界区 特性方面.
- IPC资源必须删除,否则不会自动清除,除非重启,所以system V IPC资源的生命周期随内核.

