进程间通信(IPC,InterProcessCommunication)
进程设立之初是为了私有系统资源,通信是为了两个不同进程能够同时看到公共的资源。
本质:让不同进程能够都看到同一份系统资源。只要A更改数据,B也能够看到。(借助内核,A将数据拷贝到内核上的缓冲区,B从内核缓冲区中读取)内核即操作系统。
子进程更改数据是自己的,可以看到数据的变化,但是父进程就不行,可能会触发写时拷贝;
进程间通信方式:
匿名管道、命名管道、消息队列、
信号量、
共享内存
、信号
、套接字
1、匿名管道--pipe
1.1 管道调用函数pipe:
int pipe(int pipefd[2]);
pipefd[0]---读端 pipefd[1]---写端;
pipe函数调用成功返回0,失败返回-1
调用:man 2 pipe(只用于父子间通信);父进程的文件描述表是可以进行继承的。
1.2 管道特点:
(1)管道依赖于文件系统,
(2)管道只允许父子进程或者有血缘关系的进程间通信,《匿名管道》
(3)管道只允许单向数据通信, 若要双向通信必须再设置一个管道。
(4)管道提供面向字节流数据传输符,
(5)当进程结束时,管道会被系统回收。
1.3 pipe的程序代码及运行结果
ssize_t read(int fd, void *buf, size_t count);从fd向buf中读数据。
ssize_t write(int fd, const void *buf, size_t count);将buf中的数据写到fd中。
ssize_t write(int fd, const void *buf, size_t count);将buf中的数据写到fd中。
运行结果:
1)如果写端都关闭了,这时有进程从管道读端read数据。那么管道中剩余数据被读取后,再次read会返回0,就像读到文件末尾一样。
子进程write-10次,而父进程read-20次。结果只是read了10次
2)如果写端没关闭,进程也没有向管道中写数据,这时有进程从管道读端读、read数据。那么管道中剩余的数据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。
3)如果读端都关闭了,这时有进程向管道的写端write数据。那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。
4)如果读端没关闭,进程也没有从管道中读数据,这时有进程向管道写端write数据。那么在管道被写满时再次write会阻塞,直到管道中有空位置了才写数据并返回。
2、命名管道
FIFO不同于管道之处在于它提供一个路径名与之关联。命名管道是一个设备文件。
int mkfifo(const char *path,mode_t mode);
参数---
路径,模式即存取权限,文件创建类型
使用命名管道时,必须先调用open()将其打开。同时用读写方式(O_RDWR)打开,则一定不会导致阻塞。否则,可能会阻塞。
fifo读端:
fifo写端:
Makefile:
剩下的几种通信方式见下篇:【Linux】进程间通信的几种方式(2)