• Linux--进程间通讯--FIFO(open打开)


    1. 什么是FIFO
    FIFO命名管道,也叫有名管道,来区分管道pipe。管道pipe只能用于有血缘关系的进程间通信,但通过FIFO可以实现不相关的进程之间交换数据。FIFO是Linux基础文件类型中的一种,但是FIFO文件在磁盘上没有数据块,仅仅用来标识内核中的一条通道。各进程可以打开这个文件进行read/write操作,实际上是在读写内核通道,这样就实现了进程间通信。

    创建FIFO的方式:

    使用命令创建:mkfifo 管道名,可以理解为创建一个管道伪文件。
    使用库函数创建:mkfifo()函数,并且一旦使用mkfifo()创建了一个FIFO,就可以使用open来打开它,常见的文件I/O函数都可用于FIFO。如:close、read、write、unlink等。
    实际上,创建一个FIFO命名管道的时候,内核会为FIFO(伪)文件开辟一个缓冲区,操作FIFO文件就相当于操作这个缓冲区,以此来实现进程间的通信,这种通信实际上就是文件读写的操作来实现的。(可以把FIFO理解为一个文件,一个进程向该文件写数据,另一个进程从该文件中读书数据,前提是两个进程读写的是同一个FIFO文件才能实现通信)

    2.当open一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别:

            若没有执行O_NONBLOCK(默认),只读open要阻塞到某个其他进程为写而打开此FIFO。类似的,只写open要阻塞到其他进程为读而打开它。

            若指定了O_NONBLOCK,则只读open立即返回。而只写open将出错返回-1,如果没有进程已经为读而打开该FIFO,其errno置ENXIO。

     对 FIFO 类型的文件的打开、关闭跟普通文件一样,都是使用 open 和 close 函数。如果打开时使用 O_WRONLY 选项,则打开 FIFO 写入端;如果使用 O_RDONLY 选项,则打开 FIFO 的读取端。写入端和读取端都可以被几个进程同时打开。
      管道可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便。不过值得注意的是,FIFO 是严格遵循先进先出规则的,对管道及 FIFO 的读总是从开始处返回数据,对它们的写则把数据添加到末尾,它们不支持如 lseek() 等文件定位操作,必须按照从前到后的顺序依次读写
      如果以读取方式打开 FIFO,并且还没有其他进程以写入方式打开 FIFO,open 函数将被阻塞;同样,如果以写入方式打开 FIFO,并且还没有其他进程以读取方式打开 FIFO,open 函数也将被阻塞。但是,如果 open 函数中包含 O_NONBLOCK 选项,则在上述两种情况下调用 open 函数都不被阻塞。
      与 PIPE 相同,关闭 FIFO 时,如果先关闭读取端,将导致继续往下 FIFO 中写数据的进程接收 SIG_PIPE 信号。
     

    3.代码:

    创建两个进程,一个进程向FIFO数据,一个进程从FIFO数据。

    write:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. // int mkfifo(const char *pathname, mode_t mode);
    9. // ssize_t write(int fd, const void *buf, size_t count);
    10. int main()
    11. {
    12. int cnt = 0;
    13. char *str = "message from fifo";
    14. int fd = open("./ipc-file",O_WRONLY);
    15. printf("write open success\n");
    16. while(1){
    17. write(fd,str,strlen(str));
    18. sleep(2);
    19. cnt++;
    20. if(cnt == 5){
    21. break;
    22. }
    23. }
    24. close(fd);
    25. return 0;
    26. }

    read:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. // int mkfifo(const char *pathname, mode_t mode);
    7. int main()
    8. {
    9. int cnt = 0;
    10. char buf[30]={0};
    11. if(mkfifo("./ipc-file",0700)==-1 && errno != EEXIST){
    12. printf("mkfifo fail");
    13. perror("why");
    14. }
    15. int fd = open("./ipc-file",O_RDONLY);
    16. printf("open success\n");
    17. while(1){
    18. int nread = read(fd,buf,30);
    19. printf("read %d byte from fifo/n,context :%s\n",nread,buf);
    20. cnt++;
    21. if(cnt == 3){
    22. break;
    23. }
    24. }
    25. close(fd);
    26. return 0;
    27. }

    结果:

  • 相关阅读:
    “第五十一天”
    vue3 迫不得已我硬着头皮查看了keepalive的源代码,解决了线上的问题
    复杂度为O(NlogN)的归并排序
    02_面向对象高级_继承
    Oracle数据库:创建、修改、删除、使用同义词synonym和索引index
    单例模式可以被破坏
    线段树合并
    阿里也出手了!Spring CloudAlibaba AI问世了
    C语言文件操作(1)
    C语言程序编译全流程,从源代码到二进制
  • 原文地址:https://blog.csdn.net/Herry_z/article/details/132841814