Linux进程间的通信-有名管道FIFO
管道的通信只能存在于具有亲缘关系的进程之间,比如fork
出来的子进程与父进程之间的通信可以通过管道(pipe
)来实现。那么非亲缘进程之间怎么来通信呢?这次我们来看一看有名管道(FIFO
)。
FIFO
的出现克服了非亲缘进程的通信,只要可以访问路径就可以通信,并且FIFO
采用了先进先出的原则工作,第一个写入的数据将首先被读出。
-
创建
//只有创建设备文件才使用mknod()函数 int mknod(const char *path, mode_t mod, dev_t dev); //除设备文件之外的有名管道的创建 int mkfifo(const char *path, mode_t mod);
NO. 参数 含义 1 path
创建有名管道的全路径名 2 mod
创建有名管道的模式 3 dev
创建设备文件的类型 例如:
mod
参数为S_FIFO | 0666表示创建一个有名管道并且权限为0666 -
使用
FIFO
的使用也是用open
打开。使用open
创建的有名管道的进程可能会被阻塞。打开方式 O_RDWR
不会被阻塞 O_RDONLY
阻塞,直到有写方式打开管道 O_WRONLY
阻塞,直到有读方式打开管道 -
示例
//此进程运行后一直被阻塞,直到有读方式打开有名管道FIFO #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #define fifo_name "fifo" #define buf_size 1024 int main(void){ int fd; char buf[buf_size] = "hello, wfifo!."; umask(0); if(mkfifo(fifo_name, S_IFIFO | 0666) == -1){ printf("mkfifo error.\n"); exit(1); } if(fd = open(fifo_name, O_WRONLY) == -1){ printf("open error.\n"); exit(1); } write(fd, buf, strlen(buf)+1); close(fd); exit(0); }
//读取FIFO中的数据 #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #define fifo_name "fifo" #define buf_size 1024 int main(void){ int fd; char buf[buf_size]; umask(0); fd = open(fifo_name, O_RDONLY); read(fd, buf, buf_size); printf("read contect: %s\n", buf); close(fd); exit(0); }
-
应用
使用两个有名管道,实现对于进程之间的通信。
sever.c
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <unistd.h> #define RD_FIFO "readfifo" #define WR_FIFO "writefifo" #define buf_size 1024 int main(void){ int wfd,rfd; char buf[buf_size]; int len; umask(0); if(mkfifo(WR_FIFO, S_IFIFO | 0666) == -1){ printf("can't create fifo %s because %s.\n", WR_FIFO, strerror(errno)); exit(1); } umask(0); wfd = open(WR_FIFO, O_WRONLY); if(wfd == -1){ printf("open fifo %s error because %s.\n", WR_FIFO, strerror(errno)); exit(1); } while ((rfd = open(RD_FIFO, O_RDONLY)) == -1){sleep(1);} while (1){ printf("Server: "); fgets(buf, buf_size, stdin); buf[strlen(buf)-1] = '\0'; if(strncmp (buf, "quit", 4) == 0){ close(wfd); unlink(WR_FIFO); close(rfd); exit(0); } write(wfd, buf, strlen(buf)); len = read(rfd, buf, buf_size); if(len > 0){ buf[len] = '\0'; printf("Client: %s\n", buf); } } }
client.c
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <unistd.h> #define RD_FIFO "writefifo" #define WR_FIFO "readfifo" #define buf_size 1024 int main(void){ int wfd,rfd; char buf[buf_size]; int len; umask(0); if(mkfifo(WR_FIFO, S_IFIFO | 0666)){ printf("can't create fifo %s because %s.\n", WR_FIFO, strerror(errno)); exit(1); } while ((rfd = open(RD_FIFO, O_RDONLY)) == -1){sleep(1);} wfd = open(WR_FIFO, O_WRONLY); if(wfd == -1){ printf("open fifo %s error because %s.\n", WR_FIFO, strerror(errno)); exit(1); } /*while ((rfd = open(RD_FIFO, O_RDONLY)) == -1){sleep(1);}*/ while (1){ len = read(rfd, buf, buf_size); if(len > 0){ buf[len] = '\0'; printf("Server: %s\n", buf); } printf("Client: "); fgets(buf, buf_size, stdin); buf[strlen(buf)-1] = 0; if(strncmp (buf, "quit", 4) == 0){ close(wfd); unlink(WR_FIFO); close(rfd); exit(0); } write(wfd, buf, buf_size); } }