进程间通信的目的
- 数据传输:一个进程需要将它的数据发送给另一个进程。
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程给另一个进程或一组进程发送消息,通知他或他们发生了某种事件。
- 进程控制:有些进程希望完全控制另一个进程的执行,此时控制进程希望能够拦截另一个进程的所有陷入和异常,能够及时知道他的状态改变。
进程间通信及其分类
- 管道(只能进行单向通信):匿名管道pipe、命名管道;
- System V进程间通信:消息队列、共享内存、信号量;
- POSIX进程间通信:消息队列、共享内存、信号量、互斥量、条件变量、读写锁。
管道
什么是管道
管道是Unix中最古老进程间通信的一种形式,我们把从一个进程连接到另一个进程的数据流称为管道。
匿名管道(血缘关系之间常用与父子)
fd[0]与fd[1]分别表示读写,从键盘上读取数据写到屏幕上的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
int fds[2];
char buf[100];
int len;
if(pipe(fds) == -1)
{
perror("make pipe");
exit(1);
}
//read from stdin
while(fget(buf,100,stdin))
{
len = strlen(buf);
//write into pipe
if(write(fds[1],buf,len)!=len)
{
perror("write to pipe");
break;
}
memset(buf,0x00,sizeof(buf));
//read from pipe
if((len = read(fd[0],buf,100)) == -1)
{
perror("read from pipe");
break;
}
//write to stdout
if(write(1,buf,len)!= len)
{
perror("write to stdout");
break;
}
}
}
管道的本质
管道的使用和文件一致。
管道的读写规则
没有数据可读:阻塞,暂停执行直到有数据来;
当管道满的时候:阻塞,直到读走数据;
若写端对应的文件描述符被关闭,read返回0;
若读端对应的文件描述符被关闭,write操作会产生信号,进而导致write退出;
要写的数据不大于PIPE_BUF时,保证其原子性;
写的数据大于PIPE_BUF时,Linux将不再保证写入的原子性。
管道的特点
1.只能用于共同祖先的进程之间的通信。
2.提供流式服务。
3.管道的生命周期随进程。
4.内核会对管道操作进行同步与互斥。
5.管道是半双工的。