pipe一般都要和fork结合起来用,所以多进程都是基于一个主进程产生的,有一定的关联性,假如两个毫无相关的进程要进行进程间通信,命名管道可以实现;一个进程向FIFO写数据,另一个进程从FIFO读取数据
为了保持原子操作,可以通过阻塞方式来打开FIFO,就算只有一个读进程或者只有一个写进程存在,也会阻塞住等待对应的另一个进程的出现
打开FIFO的方式有下面几种:
open(const char *path, O_RDONLY); open(const char *path, O_WRONLY); open(const char *path, O_RDONLY | O_NONBLOCK); open(const char *path, O_WRONLY | O_NONBLOCK);
如果带上O_NONBLOCK,那么表示非阻塞,这样读和写只要成功打开FIFO就返回,而不管另一面的写和读到底存在与否,这样假如读进程先打开FIFO,不管写进程有没有从FIFO写入数据,读进程打开FIFO成功就返回了,说不定根本就没读取到数据;显然假如要保持同步,理论上进行数据传输,假如读进程先打开了FIFO,如果写进程还没有写入数据,需要阻塞住等待写进程写入数据从而停止阻塞从而读出数据,假如写进程线打开了FIFO,如果读进程还没来读,也可以阻塞起来等待读进程打开了FIFO
下面就是两个独立的读写进程,来进行数据传输:
首先是写进程write.c:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #define MAXSIZE 20 int main() { const int open_mode = O_WRONLY; const char *fifo_file = "/home/lihui/this_fifo"; int fd; char ch[MAXSIZE]; if (access(fifo_file, 0) == -1) if (mkfifo(fifo_file, 0777) == -1){ printf("mkfifo failed!\n"); exit(1); } printf("Write pid: %d\n", getpid()); printf("Open mode: %d\n", open_mode); printf("Input: "); scanf("%s", ch); fd = open(fifo_file, open_mode); if (fd == -1){ printf("open fifo failed!\n"); exit(1); } if (write(fd, ch, strlen(ch)) == -1){ printf("write fifo failed!\n"); exit(1); } printf("Now write %d bytes!\n", strlen(ch)); close(fd); return 0; }
然后是读进程read.c
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h> #include <string.h> #define MAXSIZE 20 int main(){ int open_mode = O_RDONLY; int fd; char buffer[MAXSIZE]; const char *fifo_file = "/home/lihui/this_fifo"; if (access(fifo_file, 0) == -1){ printf("%s not found!\n", fifo_file); exit(1); } printf("Read pid: %d\n", getpid()); printf("Open mode: %d\n", open_mode); fd = open(fifo_file, open_mode); if (fd == -1){ printf("open fifo failed!\n"); exit(1); } memset(buffer, 0, sizeof(buffer)); if (read(fd, buffer, MAXSIZE) == -1){ printf("read fifo failed!\n"); exit(1); } printf("Now read: %s, %d bytes\n", buffer, strlen(buffer)); return 0; }
编译,执行,直接先执行读端,再来写
首先,读端会阻塞住:
[lihui@localhost ~]$ cc -o readfifo read.c [lihui@localhost ~]$ cc -o writefifo write.c [lihui@localhost ~]$ ./readfifo Read pid: 1668 Open mode: 0 光标
然后,执行写端:
[lihui@localhost ~]$ ./writefifo Write pid: 1677 Open mode: 1 Input: HelloWorld! Now write 11 bytes!
再看读端:
[lihui@localhost ~]$ ./readfifo Read pid: 1668 Open mode: 0 Now read: HelloWorld!, 11 bytes
这样可以看到进程间通信,以及阻塞情况
在写程序过程中,出了2次问题:
1:写端ch先定义的字符串指针,结果coredump了,换成字符串数组就好了
2:读端的buffer没有memset,结果会出现下面结果:
[lihui@localhost ~]$ ./a.out Read pid: 1233 Open mode: 0 Now read: Helloworld!@, 12 bytes