Linux进程通讯机制学习整理
一、为什么进程间需要通讯?
1.数据传输:
一个进程需要将他的数据发送给另一个进程(生产者与消费者关系);
2.资源共享:
多个进程间共享同样的资源(均是消费者)
3.通知事件:
一个进程需要向另一个进程发送消息,通知他发生了某种事情(类似上级对下级发送命令)
4.进程控制:
一个进程希望控制另一个进程的执行。
二、linux进程通讯发展史。
linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同。前者对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,通信进程局限在单个计算机内;后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。Linux则把两者继承了下来。
三、linux进程间通讯方式分类
(1)管道(pipe)和有名管道(FIFO)
(2)信号(signal)
(3)消息队列
(4)共享内存
(5)信号量
(6)套接字(socket)
四、通讯方法详述与编程方法
管道
分为有名管道与无名管道。
无名管道(pipo)
特点:
1)只能用于血缘关系的进程间;
2)属于半双工通讯模式,有固定的读端与写端,数据只能向一个方向移动;
3)是一种特殊的文件,存在于内存中,不能通过路径访问,但可通过read\write对其操作,为了保证父子进程都有操作无名管道的一对文件描述符,必须在创建子进程前创建无名管道。
编程
函数pipe();
头文件 |
#include<unistd.h> |
函数原型 |
Int pipe(int fd[2]) |
函数传入值 |
fd[2]:管道的两个文件描述符 |
函数返回值 |
如果系统调用成功,
返回0。如果系统调用失败返回-1: |
|
|
注意:fd[0]用于读取管道,fd[1]用于写入管道。该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,
然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。一般文件的I/O函数
都可以用于管道,如close、read、write等等。
举例说明:在父进程中通过无名管道写入数据,子进程读出。
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int fd[2];
pid_t pid;
char buff[20]={0};
int num =0;
int err;
err = pipe(fd);//创建无名管道
if(err<0)
{
printf("pipe creat err\n");
return -1;
}
if((pid=fork()) == 0)
{
close(fd[1]);//关闭写
sleep(5);//等待有数据写入
printf("\n");
num = read(fd[0],buff,100);
if(num)
{
printf("read_num=%d, %s\n",num,buff);
}
close(fd[0]);
exit(0);
}
else if(pid>0)
{
close(fd[0]);
if(write(fd[1],"hello word",11)!=-1)
{
printf("parent write:hello word\n");
}
close(fd[1]);
waitpid(pid,NULL);//等待子进程结束
exit(0);
}
return 0;
}
运行结果