1.进程通信的目的
(1) 数据传输: 一个进程需要将它的数据传输给另一个进程
(2) 资源共享: 多个进程之间共享同样的资源
(3) 通知事件: 一个进程需要向另一个或一组进程发送消息, 通知它们发生了什么事情
2.管道
管道是一种进程之间通信的一种方式, 我们把从一个进程连接到另一个进程的数据流叫做管道
3.匿名管道
(1) 匿名管道的创建
int pipe(int fd[2]);
fd是一个文件描述符数组, fd[0] 代表读端, fd[1] 代表写端
返回值:成功过时返回0, 失败时返回错误代码
4.代码演示
//clientPipe.c
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>int main()
{int wfd = open("mypipe", O_WRONLY);if(wfd == -1)//dakashibai{perror("open");exit(1);}char buf[1024];buf[0] = 0;ssize_t s;while(1){printf("Please Enter#");fflush(stdout);s = read(0, buf, sizeof(buf));if(s > 0)//成功读取{buf[s] = 0;write(wfd, buf, s);}else if(s <= 0)//读取失败{perror("read");exit(1);}}
}//serverPipe.c
#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/types.h>int main()
{int fifo = mkfifo("mypipe", 0644);if(fifo == -1)//管道创建失败{perror("mkfifo");exit(1);}//打开管道int rfd = open("mypipe", O_RDONLY);if(rfd == -1)//打开失败{perror("open");exit(1);}//读管道数据char buf[1024];ssize_t s;while(1){buf[0] = 0;printf("Please wait ... \n");s = read(rfd, buf, sizeof(buf) -1);if(s > 0)//读到数据{buf[s] = 0;printf("client say# %s", buf);}else if(s == 0)//读完{printf("client quit, exit now\n");exit(0);}else//读取失败{perror("read");exit(1);}}close(rfd);return 0;
}
5.站在文件描述符角度理解
父进程先创建管道, 创建完管道,同时父进程打打开对应的读端和写端,接着父进程创建子进程, 由于子进程会继承父进程的特性, 因此子进程也会打开和父进程一样的读端和写端, 此时父子进程就看到了一份公共资源, 紧接着父进程将读端关闭, 子进程将写端关闭, 于是便可以父进程进行对数据的写,子进程只管从管道中读数据即可,于此父子进程合作完成读写工作.
6.管道读写规则
(1) 当管道读端关闭, 写端还在继续写的时候此时操作系统会给写端发送一个 SIGPIPE 的信号,从而使得写端退出
(2) 如果写端对应的描述符关闭, 读端则会正常退出.
(3) 管道具有上限,当写到 PIPE_BUF 时, Linux 将不再保证其写入的原子性.
(4) 注意匿名管道对应的两个进程之间一定是由血缘关系的
7. 管道特点
(1) 管道具有单向性
(2) 有血缘关系的进程之间才能进行通信(匿名管道)
(3) 管道必须满足同步互斥关系(管道没有数据时,读端进程将会不读,阻塞等待, 当管道已经满的时候就不能对管道进行写了)
(4) 管道的生命周期随进程
(5) 管道提供字节流服务(从管道中一次读多少由操作系统决定, 即一次读写多少不确定)
8. 相关的几个概念
(1) 数据不一致: 一个进程的读写影响到另外一个进程的读写
(2) 临界资源: 两个进程看到的一份公共资源,并且一次只允许一个进程使用
(3) 临界区: 进程访问临界资源的那段代码就叫做临界资源
(4) 互斥: 各进程有时需要共享资源, 而且有些资源需要互斥访问, 因此进程之间竞争使用这些资源, 进程之间的这种关系叫做互斥
(5) 进程访问资源的原子性: 进程在操作某些资源时要不做完, 要不不做, 中间不会收到如何其他进程的干扰.
(6) 同步: 进程之间以一种比较安全的顺序访问资源, 这种安全机制就叫做同步
(7) 管道自带同步互斥机制, 当管道中没有数据时父进程会等待子进程的退出