首页 > linux进程间通信:命名管道FIFO

linux进程间通信:命名管道FIFO

文章目录

        • FIFO 通信特点
        • 系统调用接口
        • 应用
          • 拥有亲缘关系之间的进程通信
          • 非亲缘关系进程之间的通信
        • 总结

FIFO 通信特点

  • FIFO文件有文件名
    • 可以像普通文件一样存储在文件系统之中
    • 可以像普通文件一样使用open/write读写
    • 和pipe文件一样属于流式文件,不能使用lseek系统调用重定位文件偏移地址
  • 具有写入原子性,支持多个进程同时对FIFO进行写操作,如日志系统/var/log
  • First in First out,先入先出。最先被写入的数据最先被读出来
    • 默认阻塞读,阻塞写的特性。可以在open的时候进行设置
    • 如果一个进程打开fifo的一端时,令一端没有打开,该进程会被阻塞。

fifo与pipe最大的区别就是pipe只能用于亲缘进程之间的通信(fork方式创建的父子进程),但是fifo可以支持任意两个进程之间的通信,并包括拥有亲缘关系的进程

系统调用接口

  • shell命令:mkfifo pathname,可以通过man mkfifo查看命令用法
  • 函数接口:int mkfifo(const char *pathname,mode_t mode)
  • 函数功能:创建fifo的有名管道
  • 函数参数:

    - pathname FIFO管道文件名

    - mode 读写权限

应用

拥有亲缘关系之间的进程通信

通信过程类似于pipe的fd[0]读出,fd[1]写入


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include #define FIFO "testfifo"
int main()
{ int a=mkfifo(FIFO,0644);if (0 != a)printf("mkfifo failed %d
",a);int ret,fifo_fd;ret = fork();if (ret == -1) { perror("fork");_exit(-1);}//子进程负责写入管道else if (ret == 0) { fifo_fd = open("testfifo",O_RDWR);char buf[100];memset(buf,0,100);printf("child process(%d) input msg:",getpid());//scanf("%s",buf);fgets(buf,10,stdin);int write_len = write(fifo_fd,buf,strlen(buf));printf("%d bytes has been sent
",write_len);_exit(1);}//父进程进行从管道进行读取else { sleep(5);fifo_fd = open("testfifo",O_RDWR);char buf[100];memset(buf,0,100);printf("father process befor read
");int read_len = read(fifo_fd,buf,100);if (read_len == -1)printf("read error %d
",read_len);printf("father process(%d) read message from fifo :%s
",getpid(),buf);_exit(1);}return 0;
}
非亲缘关系进程之间的通信

写端:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include #define FIFO_NAME "testfifo"int main(int argc, char* argv[])
{ int fd;char buf[100];mkfifo(FIFO_NAME, S_IFIFO|0666);//循环向testinfo中写入数据while (1){ printf("please input the string : 
");fd = open(FIFO_NAME, O_WRONLY);fgets(buf,100,stdin);write(fd, buf, strlen(buf)+1);close(fd);}unlink(FIFO_NAME); //删除命名管道文件sleep(1);return 0;
}

读端:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include #define FIFO_NAME "testfifo"
#define BUF_SIZE 1024int main(int argc, char* argv[])
{ int fd;char buf[BUF_SIZE];//循环从testinfo中读取数据while (1) { fd = open(FIFO_NAME, O_RDONLY);//read系统调用会从打开的文件当前文件偏移地址开始读,即上次写入的数据read(fd, buf, BUF_SIZE);printf("%s
", buf);close(fd);}return 0;
}

总结

为什么无名管道只能用于父子进程之间的通信呢?无名管道是一个文件,但是只能存在与内存之中,且该文件的读写方式是固定的,我们只能从一端写入,一端读出。使用无名管道通信,他得文件句柄需要在同一个进程内共享。即在同一个进程内只有fork的方式,能够将当前进程所有文件描述符以及进程状态信息拷贝给另一个进程;只有在这样的进程关系之下,无名管道的数据传输才能实现一端写入,一端读出。

命名管道fifo可以像普通文件一样存在与操作系统磁盘之中,同样支持read/write的数据读写,因此它能够被多个进程共同访问。虽然fifo相比于pipe使用范围扩大了,但是总体的阻塞式通信依然存在。

pipe的内核实现fs/pipe.cpipe_readpipe_write函数处理过程中都是通过加锁mutex来实现,并没有相关的异步操作,而fifo的fifo_open函数同样是阻塞式处理函数体。

更多相关:

  • 关于点云的分割算是我想做的机械臂抓取中十分重要的俄一部分,所以首先学习如果使用点云库处理我用kinect获取的点云的数据,本例程也是我自己慢慢修改程序并结合官方API 的解说实现的,其中有很多细节如果直接更改源程序,可能会因为数据类型,或者头文件等各种原因编译不过,会导致我们比较难得找出其中的错误,首先我们看一下我自己设定的一个场景,...

  • /* 使用正态分布变换进行配准的实验 。其中room_scan1.pcd room_scan2.pcd这些点云包含同一房间360不同视角的扫描数据 */ #include #include #include #include

  • #include #include #include #include ...

  • #include #include #include #include #include #include...

  • #include #include #include #include int main (int argc,...

  • 在我们面试过程中,面试官经常会问到这么一个问题,那就是从在浏览器地址栏中输入URL到页面显示,浏览器到底发生了什么?这个问题看起来是老生常谈,但是这个问题回答的好坏,确实可以很好的反映出面试者知识的广度和深度。本文从浏览器角度来告诉你,URL后输入后按回车,浏览器内部究竟发生了什么,读完本文后,你将了解到:浏览器内有哪些进程,这些...

  • 进程与线程进程(process)就是任务,是计算机系统进行资源分配和调度的基本单位[1]。比如,打开一个word文件就是启动了一个word进程。线程(thread)是进程内的子任务。比如word中可以进行编辑、拼写检查和打印等子任务。我们目前的操作系统都是多任务的操作系统,多任务的实现方式[2]:多进程多线程多进程 + 多线程多进程:...

  • 运行cmd netstat -aon|findstr 80 然后 taskkill -f -pid 32428(这个就是pid进程编号) 回车   进程死翘翘了~ 去愉快玩耍吧~哦对了 别忘记一健三联关注我哟~...

  • 首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网...

  • 1.      SIGTERM “kill pid” 会发送SIGTERM到进程pid. This is the termination signal sent by killcommand by default. 2.      SIGINT 在终端中敲入interrupt key(DELETE或ctrl+c)会产生SIG...

  •         NSString * str = @"123";char buf[20];[str getCString:buf maxLength:20 encoding:NSASCIIStringEncoding];NSLog(@"%s",buf); 转载于:https://blog.51cto.com/8947509/1...

  • sscanf 目录 名称:函数原型:头文件:说明:支持集合操作:例子: 编辑本段名称:   sscanf() - 从一个字符串中读进与指定格式相符的数据. 编辑本段函数原型:   Int sscanf( const char *, const char *, ...);   int scanf( const char...