IPC通信_有名管道(FIFO)
与无名管道不同,有名管道FIFO可以在两个无关进程间使用。
#include <sys/stat.h> int mkfifo(const char* path, mode_t mode);
上述函数用于生成一个FIFO文件,其中的mode参数与open函数中的mode相同。当创建了FIFO文件后,要用open函数来打开它。
当open一个FIFO时,非阻塞标志(O_NONBLOCK)会有如下影响:
O_NONBLOCK标志 |
详 细 说 明 |
置位 |
只读open立即返回;只写open时,如果没有进程为读打开FIFO,则返回–1,并置errno值为ENXIO |
不置位 |
open视情况阻塞。只读open要阻塞到有进程为写打开FIFO;只写open要阻塞到有进程为读打开FIFO |
两点注意:
1、如果write一个尚无进程为读而打开的FIFO,则产生信号SIGPIPE。
2、如果某个FIFO的最后一个写进程关闭了该FIFO,则将为该FIFO的读进程产生一个文件结束标志。
举例:两个程序,一个读,一个写,且写程序加了SIGPIPE信号处理函数,读程序在读到结束符后加了打印,可以验证上面所有描述。
fifo_read.cpp:
#include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <stdio.h> #include <string> #include <iostream> int main() { const char* path = "/tmp/tmp_fifo"; // 判断是否有fifo文件,没有就创建一个 if(access(path, F_OK) == -1) { printf("create %s\n",path); if(mkfifo(path,0777) == -1) { printf("create failed\n"); return -1; } } int pipe_fd = open(path, O_RDONLY);//只读模式打开 if(pipe_fd < 0) { printf("open %s failed\n",path); return -1; } else { printf("open %s success\n",path); } char buf[128] = {0}; while(read(pipe_fd, buf, 128)) { printf("read: %s\n",buf); } printf("read end\n"); close(pipe_fd); return 0; }
fifo_write.cpp:
#include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string> #include <iostream> #include <signal.h> void handler(int arg) { printf("signal PIPE\n"); } int main() { signal(SIGPIPE, &handler); const char* path = "/tmp/tmp_fifo"; // 判断是否有fifo文件,没有就创建一个 if(access(path, F_OK) == -1) { printf("create %s\n",path); if(mkfifo(path,0777) == -1) { printf("create failed\n"); return -1; } } int pipe_fd = open(path, O_WRONLY);//只写模式打开 if(pipe_fd < 0) { printf("open %s failed\n",path); return -1; } else { printf("open %s success\n",path); } char buf[128] = {0}; std::string str; while(std::cin>>str) { write(pipe_fd, str.c_str(), str.size()); printf("write : %s\n",str.c_str()); } close(pipe_fd); return 0; }