1、进程间通讯概念
◼ 进程是一个独立的资源分配单元,不同进程(这里所说的进程通常指的是用户进程)之间的资源是独立的,没有关联,不能在一个进程中直接访问另一个进程的资源。
◼ 但是,进程不是孤立的,不同的进程需要进行信息的交互和状态的传递等,因此需要进程间通信
( IPC:Inter Processes Communication )。 ◼ 进程间通信的目的:
◼ 数据传输:一个进程需要将它的数据发送给另一个进程。
◼ 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
◼ 资源共享:多个进程之间共享同样的资源。为了做到这一点,需要内核提供互斥和同步机制。
◼ 进程控制:有些进程希望完全控制另一个进程的执行(如 Debug 进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
2、进程间通信方式
3、 匿名管道
◼ 管道也叫无名(匿名)管道,它是是 UNIX 系统 IPC(进程间通信)的最古老形式,所有的 UNIX 系统都支持这种通信机制。
◼ 统计一个目录中文件的数目命令:ls | wc –l,为了执行该命令,shell 创建了两个进程来分别执行 ls 和 wc。
其中 | 是管道符,后面统计个数 ,| 创建管道,将 ls 传输到 wc 中
4、管道的特点
◼(1) 管道其实是一个在内核内存中维护的缓冲器,这个缓冲器的存储能力是有限的,不同的操作系统大小不一定相同。
◼ (2)管道拥有文件的特质:读操作、写操作,匿名管道没有文件实体,有名管道有文件实体,但不存储数据。可以按照操作文件的方式对管道进行操作。
◼(3) 一个管道是一个字节流,使用管道时不存在消息或者消息边界的概念,从管道读取数据的进程可以读取任意大小的数据块,而不管写入进程写入管道的数据块的大小是多少。
◼ (4)通过管道传递的数据是顺序的,从管道中读取出来的字节的顺序和它们被写入管道的顺序是完全一样的。
◼(5) 在管道中的数据的传递方向是单向的,一端用于写入,一端用于读取,管道是半双工的。
◼ (6)从管道读数据是一次性操作,数据一旦被读走,它就从管道中被抛弃,释放空间以便写更多的数据,在管道中无法使用 lseek() 来随机的访问数据。
◼ (7)匿名管道只能在具有公共祖先的进程(父进程与子进程,或者两个兄弟进程,具有亲缘关系)之间使用。
5、 为什么可以使用管道进行进程间通信
子进程和父进程共享文件描述符,可以进行通信
6、 管道的数据结构
通过逻辑关系线性队列设计为环形队列
7、匿名管道的使用
(1) 创建匿名管道
#include <unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
//子进程发送数据给父进程,父进程读取数据输出
//parent recv: Hello,I am child,pid:17384
int main()
{
// 在fork之前创建管道
int pipefd[2];
int ret= pipe(pipefd);
if(ret==-1)
{
perror("pipe");
exit(0);
}
//创建子进程
pid_t pid =fork();
if(pid>0)
{
//父进程
printf("I am parent process,pid:%d\n",getpid());
//读取数据,从管道的读取段读取数据
char buf[1024]={0};
while(1)
{
int len=read(pipefd[0],buf,sizeof(buf));
printf("parent recv: %s,pid:%d\n",buf,getpid());
//向管道中写入数据
char * str="Hello,I am parent";
write(pipefd[1],str,strlen(str));
sleep(1);
}
}
else if(pid ==0)
{
sleep(10);
//子进程
//写入数据
char buf[1024]={0};
printf("I am child process,pid:%d\n",getpid());
while(1)
{
//向管道中写入数据
char * str="Hello,I am child";
write(pipefd[1],str,strlen(str));
sleep(1);
}
//读取数据
int len=read(pipefd[0],buf,sizeof(buf));
printf("child recv: %s,pid:%d\n",buf,getpid());
}
return 0;
}
(2)查看管道缓冲大小命令
ulimit –a
当前Linux 系统中 pipe size : (512 bytes, -p) 8
(3)查看管道缓冲大小函数
#include <unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<string.h>
int main()
{
int pipefd[2];
int ret=pipe(pipefd);
long size =fpathconf(pipefd[0], _PC_PIPE_BUF); //获取管道的大小
printf("pipe size: %ld\n",size);
return 0;
}
结果为:pipe size: 4096