进程之间的通信有两种,无名管道通信和有名管道通信,
为什么有通信呢,可以理解为你有一个同事,你两干一件事从不同的方向,哪一件事你干,哪一件事他干,你俩得知道吧,差不多是这个意思
无名管道
无名管道的特点:
无名管道属于单向通讯
无名管道只能用于父子进程通讯
无名管道发送端叫做写端,接收端叫做读端
无名管道将读端与写端抽象成两个文件进行操作,在无名管道创建成功之后,则会返回将读端与写
端的文件描述符存入数组
创建无名管道
创建无名管道需要调用 pipe() 函数
函数头文件
#include <unistd.h>
功能
管道创建之后,内核会将文件描述符存储到数组
函数原型
int pipe(int pipefd[2]);
函数参数
pipefd:用于存储无名管道读端与写端的文件描述符的数组
pipefd[0]:读端文件描述符
pipefd[1]:写端文件描述符
函数返回值:
成功:0
失败:-1,设置 errno
总结:
1. 当管道为空时,读进程会阻塞
2. 当管道的写端被关闭,从管道中读取剩余数据后,read 函数返回0
3. 在写入管道时,确保不超过PIPE_BUF字节的操作是原子的
4. 管道的大小是有限的,不能让父/子进程同时对管道进行读/写操作
5. 当一个进程试图向管道中写入数据,但没有任何进程拥有该管道的打开着的读取描述符,内核向写入进程发送一个SIGPIPE信号(后面信号量会提到)
有名管道
有名管道是文件系统中可见的文件,但是不占用磁盘空间,仍然在内存中。可以通过 mkfifo命令创建有名管道(在linux共享目录不能使用mkfifo)
有名管道与无名管道一样,在应用层是基于文件接口进行操作
有名管道用于任意进程之间的通讯,当管道为空时,读进程会阻塞
如果有名管道的一端以只读方式打开,它会阻塞到另一端以写的方式(只写,读写)
如果有名管道的一端以只写方式打开,它会阻塞到另一端以读的方式(只读,读写)
读端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define PIPE_NAME "/home/linux/pipe2"
int main()
{int fd = open(PIPE_NAME,O_RDONLY);if(fd == -1){perror("read");exit(EXIT_FAILURE);}char buf[256]={0};ssize_t rbytes = read(fd,buf,sizeof(buf));if(rbytes > 0){printf("content:%s\n",buf);}close(fd);return 0;
}
写端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define PIPE_NAME "/home/linux/pipe2"
int main()
{int ret = access(PIPE_NAME,F_OK);if(ret == -1){mkfifo(PIPE_NAME,0644);}int fd = open(PIPE_NAME,O_WRONLY);if(fd == -1){perror("open");exit(EXIT_FAILURE);}char buf[256]={"Hello pipe."};ssize_t wbytes = write(fd,buf,sizeof(buf));if(wbytes == -1){perror("write");close(fd);exit(EXIT_FAILURE);}close(fd);return 0;
}
有名管道的优缺点
优点
可以实现任意进程间通信,操作起来和文件操作一样
缺点:
1.打开的时候需要读写一起进行否则就会阻塞,管道大小是 4096个字节
2.半双工的工作模式,如果和多个进程通信则需要创建多个管道