Linux下进程间通信的常用方法
0. 文件
利于进程间共享文件描述符的特性实现。开销最大,已经废弃。
1. 无名管道pipe
原理:通过内核缓存区和循环队列实现;
特性:1.两个文件描述符,数据从一端写入,另一端读出,单向通信;
2.读数据时:如果管道有数据,直接读取并返回读取的字节数;
如果管道没数据,如果所有的写端都关闭了,读取返回0;如果还有写端打开,阻塞等待写端写数据;
3.写数据时:如果读端全部关闭,就会收到一个SIGPIPE信号而进程异常终止;
如果有读端打开,如果管道没满,写数据并返回的字节数;如果管道满了,阻塞等待读端读数据;
缺点:1.单向通信(半双工通信方式),一个进程只能读或者写,不能同时读和写
2.数据不能反复读,一旦读走了,就不在该内核缓存区了
3.只能用于有血缘关系的进程间通信
函数:int pipe(int pipefd[2]); //pipefd是长度为2的int数组,传出参数;pipefd[0]是读端文件描述符,pipefd[1]是写端文件描述符
举例说明:
int main(int argc, char *argv[]) {
int pipefd[2]; pid_t cpid; char buf;
if (pipe(pipefd) == -1) { perror("pipe");exit(EXIT_FAILURE);}//创建管道失败,直接退出
cpid = fork();
if (cpid == -1) { perror("fork");exit(EXIT_FAILURE);}//创建子进程失败,直接退出
if (cpid == 0) { //子进程
close(pipefd[1]);//这里让子进程读取数据,关闭写端;pipefd[0]读端,pipefd[1]写端
while (read(pipefd[0], &buf, 1) > 0) //读数据到buf;长度大于0,说明读取到数据;0表示所有写端关闭了
write(STDOUT_FILENO, &buf, 1); //将数据输出到标准输出
close(pipefd[0]); //关闭读端
_exit(EXIT_SUCCESS);
} else { //父进程
close(pipefd[0]); //让父进程写数据,关闭读端
write(pipefd[1], argv[1], strlen(argv[1])); //将参数argv[1]写入管道;所以命令行运行需要带参数,如./test "hello world"
close(pipefd[1]); //关闭写端
wait(NULL); //等待子进程退出
exit(EXIT_SUCCESS);
}
}
2. 有名管道fifo
原理:fifo是Linux文件系统里的一种基础文件类型
特性:必须使用同一个fifo文件才能通信;可以同时多端读、多端写;和pipe最大的区别是 可用于无血缘关系的进程间通信
函数:int mkfifo(const char *pathname, mode_t mode); //pathname文件路径,mode八进制权限
该函数创建一个fifo类型的文件,也可以使用mkfifo手动创建;
举例说明:1.先创建好一个fifo文件,可代码创建也可以命令行创建;2.向这个fifo文件读写数据,和普通文件读写类似
fd = open("test", O_RDONLY);read(fd, buf, sizeof(buf));//test是fifo文件,一个进程只读方式打开该文件读数据
fd = open("test", O_WRONLY);write(fd, buf, strlen(buf));//test是同一个fifo文件,另一个进程只写方式打开写入数据
3.共享存储映射区mmap、munmap
//todo
4. 信号 (开销最小)
//todo
5.套接字 (最复杂,但最稳定)
//todo