进程间通信的方式
管道、信号量、共享内存、消息队列
管道
定义:当一个进程连接数据流到另一个进程时,使用管道。通常是把一个进程的输出通过管道连接到另一个进程的输入。
管道是由内核管理的一个缓冲区(buffer),相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都结束的时候,管道也自动消失。
- 管道文件(大小永远为0,写入管道的数据在内存中写着)
- 创建有名管道,位于文件系统
命令形式:
mkfifo fifo
函数形式:
int mkfifo(const char * filename,mode_t mode)
-
必须有两个进程同时打开管道文件,一个读一个写
-
无名管道位于内存
-
管道属于半双工的通讯方式(单向的数据流)
-
写端彻底关闭,读端把已有数据读完之后read返回值为0
-
读端关闭,写端引发异常,收到信号(SIGPIPE),终止
-
管道最大的写入值是4kb
分类
无名管道
用来在相关的程序之间传递数据,即这些程序是由一个共同的祖先进程启动的。
int pipe(int file_descriptor[2]);
//pipe函数的参数时一个由两个整形类型的文件描述符组成的数组的指针。
两个返回的描述符以一种特殊的方式连接起来,写到file_descriptor[1]的所有数据都可以从好file_descriptor[0]读回来。数据基于先进先出的原则进行处理
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
int main()
{
int fd[2];
pipe(fd);//fd[0] r ,fd[1] w
pid_t pid = fork();
assert( pid != -1 );
if ( pid == 0 )
{
close(fd[1]);//关闭写端
char buff[128] = {
0};
read(fd[0],buff,127);//子进程用来从管道读取父进程写入的数据
printf("child buff=%s\n",buff);
close(fd[0]);
}
else
{
close(fd[0]);//关闭读端
printf("input:\n");
char buff[128] = {
0};
fgets(buff,128,stdin);
write(fd[1],buff,strlen(buff));