Linux进程间通信之管道
1,进程间通信 (IPC ) Inter-Process Communication
比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息。
2,linux下IPC机制的分类:管道、信号、共享内存、消息队列、信号量、套接字
3,这篇主要说说管道:本质是文件,其他理论什么的网上已经有一大堆了,我就只写一点用法吧。
3.1 特点
1)管道是最古老的IPC,但目前很少使用
2)以文件做交互的媒介,管道分为有名管道和无名管道
3)历史上的管道通常是指半双工管道
3.2 管道:有两种形式,命令行和非命令行
(1)命令行:
mkfifo testfifo
echo "testfifo" >fifo
cat fifo
(2)非命令行:这里又分有名管道和无名管道
编程模型:进程A创建管道(mkfifo) -> 进程A写打开管道(open) -> 进程B读打开管道(open) -> 进程A开始往管道里写数据(write) ->
进程B从管道中读数据(read) -> 进程A关闭管道(close) -> 进程B关闭管道(close) -> 删除管道(unlink)
有名管道(实例):
进程A:
#include<sys/stat.h> #include<fcntl.h> #include<stdio.h> #define PIPENAME "pipetest" int main() { // 创建管道 if(mkfifo(PIPENAME, 0666) < 0) { perror("mkfifo"); return -1; } // 写打开管道 int fd = open(PIPENAME, O_WRONLY); if(-1 == fd) { perror("open"); return -1; } unlink(PIPENAME); int i = 0; for(i = 0; i < 10; i++) { write(fd, &i, sizeof(i)); printf("%d\n", i); sleep(1); // 这个是以秒为单位挂起 } // 关闭管道 close(fd); return 0; }
进程B:
#include<sys/stat.h> #include<fcntl.h> #include<stdio.h> #define PIPENAME "pipetest" int main() { // 读打开管道 int fd = open(PIPENAME, O_RDONLY); if(-1 == fd) { perror("open"); return -1; } int num = 0; int i = 0; for(i = 0; i < 10; i++) { read(fd, &num, sizeof(int)); printf("%d\n", num); fflush(stdout); // 强制刷新输出缓冲区 } printf("\n"); close(fd); return 0; }
运行效果如下:
开另外一个终端,运行读进程
无名管道:适用于父子进程之间的通信
int pipe(int pipefd[2]):该函数在内核中创建管道文件,通过输出参数pipefd返回两个文件描述符,其中pipefd[0]用于读,pipefd[1]用于写。
注意:
写数据的进程关闭读端pipefd[0]
读数据的进程关闭写端pipefd[1]
实例:
#include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<stdlib.h> int main() { int fd[2]; // 用来保存文件描述符 pipe(fd); pid_t pid = fork();// 创建进程 if(pid > 0) { // 父进程写管道,需要关闭读端 close(fd[0]); int i = 0; for(i=10; i<20; i++) { write(fd[1], &i, sizeof(int)); sleep(1); } close(fd[1]);// 关闭写端 exit(0); } // 子进程读管道 close(fd[1]); // 先关闭写端 int x; int i = 0; for(; i<10; i++) { read(fd[0], &x, sizeof(int)); printf("%d ", x); setbuf(stdout, NULL); } close(fd[0]); printf("\n"); return 0; }
运行效果如下: