Linux内核实现进程通讯
思路
FIFO 和 Pipe 一样,提供了双向进程间通信渠道。但要注意的是,无论是有名管道还 是匿名管道同一条管道只应用于单向通信,否则可能出现通信混乱(进程读到自己发的 数据)
采用库函数 mkfifo() 创建fifo有名管道.
函数说明:
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <sys/types.h> #include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
|
管道发送端
创建fifo_write.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include <stdio.h> #include "stdlib.h" #include "sys/types.h" #include "sys/stat.h" #include "unistd.h" #include "fcntl.h" #include "string.h" #include "errno.h"
int main(int argc,char *argv[]) { char *pipe_path="/tmp/fifo"; int resFifo=mkfifo(pipe_path,0664); if(resFifo!=0){ perror("mkfifo error"); exit(EXIT_FAILURE); } int fd= open(pipe_path,O_WRONLY); if(fd ==-1){ perror("open error"); exit(EXIT_FAILURE); } char buffer[100]; ssize_t readNum; while((readNum= read(STDIN_FILENO,buffer,sizeof(buffer)))>0){ write(fd,buffer, readNum); } if (readNum<0){ perror("read error"); close(fd); exit(EXIT_FAILURE); } printf("写入成功\n"); return 0; }
|
管道接收端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <stdio.h> #include "stdlib.h" #include "sys/types.h" #include "sys/stat.h" #include "unistd.h" #include "fcntl.h" #include "string.h" #include "errno.h"
int main(int argc,char *argv[]) { char *pipe_path="/tmp/fifo"; int fd= open(pipe_path,O_RDONLY); if(fd ==-1){ perror("open error"); exit(EXIT_FAILURE); } char buffer[100]; ssize_t readNum; while((readNum= read(fd,buffer,sizeof(buffer)))>0){ write(STDOUT_FILENO,buffer, readNum); } if (readNum<0){ perror("read error"); close(fd); exit(EXIT_FAILURE); } printf("读取成功\n"); return 0; }
|
Makefile编译
1 2 3 4 5 6
| CC :=gcc fifo_read: fifo_read.cpp -$(CC) -o $@ $^
fifo_write: fifo_write.cpp -$(CC) -o $@ $^
|
注意
调用 open()打开有名管道时,flags 设置为 O_WRONLY 则当前进程用于向有名管道写 入数据,设置为 O_RDONLY 则当前进程用于从有名管道读取数据。设置为 O_RDWR 从技术 上是可行的,但正如上文提到的,此时管道既读又写很可能导致一个进程读取到自己发送 的数据,通信出现混乱。因此,打开有名管道时,flags 只应为 O_WRONLY 或 O_RDONLY。
内核为每个被进程打开的 FIFO 专用文件维护一个管道对象。当进程通过 FIFO 交换数 据时,内核会在内部传递所有数据,不会将其写入文件系统。因此,/tmp/myfifo 文件大 小始终为 0