1.进程通信的目的
(1) 数据传输: 一个进程需要将它的数据传输给另一个进程
(2) 资源共享: 多个进程之间共享同样的资源
(3) 通知事件: 一个进程需要向另一个或一组进程发送消息, 通知它们发生了什么事情
2.管道
管道是一种进程之间通信的一种方式, 我们把从一个进程连接到另一个进程的数据流叫做管道
3.匿名管道
(1) 匿名管道的创建
int pipe(int fd[2]);
fd是一个文件描述符数组, fd[0] 代表读端, fd[1] 代表写端
返回值:成功过时返回0, 失败时返回错误代码
4.代码演示
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<error.h>
#include<stdlib.h>int main()
{int fd[2];int pip = pipe(fd);if(pip == -1){perror("pipe");exit(1);}pid_t id = fork();if(id == -1){perror("fork");exit(1);}if(id == 0){close(fd[0]);write(fd[1], "hello", 5);close(fd[1]);exit(0);}close(fd[1]);char buf[100];int len = read(fd[0], buf, strlen(buf));if(len == -1){perror("read");exit(1);}printf("%s\n", buf);return 0;
}
5.站在文件描述符角度理解
6.匿名管道的特点
(1) 单向
(2) 有血缘关系的进程才能通信
(3) 同步互斥机制(管道没有数据了就不读了, 管道满了就不能写了)
(4) 进程退出管道释放,管道的生命周期随进程
(5) 管道提供面向字节流的服务
7.几个名词概念
(1) 字节流: 由上层决定, 一次读多少不确定
(2) 数据不一致: 一个进程读, 另一个进程写
(3) 临界区: 两个进程访问临界资源的那段代码叫做临界区
(4) 互斥: 在任何一个时间点临界区访问临界资源时只允许一个进程访问
(5) 访问资源的原子性: 进程在操作某些资源时要么不做, 要么做完,中间不会被打扰
(6) 同步: 以相对比较安全的顺序访问资源,这种安全性叫同步(为了防止饥饿现象)
(7) 管道自带互斥和同步, 当管道里无数据时, 父进程会等子进程退出
8.管道满的时候
(1) 所有管道写端对应的文件描述符被关闭时, 则read返回0
(2) 如果所有文件描述符读端对应文件描述符被关闭时, 则write 操作会产生一个SIGPIPE, 进而可能导致write进程退出
(3) 当要写的数据不大于PIPE_BUF时(4096), Linux将保证写入的原子性
(4) 当写的数据大于PIPE_BUF时, Linux将不再保证写入的原子性