【Linux进程间通信】三、FIFO命名管道

简介: 【Linux进程间通信】三、FIFO命名管道

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. FIFO编程实战

示例: 使用FIFO实现进程间通信

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

/************************************************************
  >File Name  : write_fifo.c
  >Author     : Mindtechnist
  >Company    : Mindtechnist
  >Create Time: 2022年05月21日 星期六 22时38分08秒
************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char* argv[])
{
    if(argc < 2)
    {
        printf("not fount fifoname\n");
        return -1;
    }
    /*打开一个fifo文件*/
    int fd = open(argv[1], O_WRONLY);
    /*写FIFO文件*/
    char buf[256];
    int count = 1;
    while(1)
    {
        memset(buf, 0, sizeof(buf));
        /*循环写入*/
        sprintf(buf, "count %04d", count++);
        /*写入FIFO*/
        write(fd, buf, strlen(buf));
        sleep(1);
    }
    close(fd);
    return 0;
}
/************************************************************
  >File Name  : read_fifo.c
  >Author     : Mindtechnist
  >Company    : Mindtechnist
  >Create Time: 2022年05月22日 星期日 09时54分37秒
************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char* argv[])
{
    if(argc < 2)
    {
        printf("not found fifoname\n");
        return -1;
    }
    int fd = open(argv[1], O_RDONLY);
    char buf[256] = {0};
    int ret;
    while(1)
    {
        memset(buf, 0, sizeof(buf));
        ret = read(fd, buf, sizeof(buf));
        if(ret > 0)
        {
            printf("read buf: %s\n", buf);
        }
    }
    close(fd);
    return 0;
}

编译两个程序生成可执行文件,并使用命令mkfifo创建一个FIFO

测试的时候,我们在SecureCRT中克隆一个会话(相当于在Linux中打开两个shell终端),一个运行写进程,一个运行读进程。要注意的是,应该先运行写进程再运行读进程。

同时我们也可以打开多个进程去读写这同一个FIFO缓冲区,当多个进程去读的时候,被读进程1读走的数据就不会再被进程2读取了,比如说下面图中所示,这个进程读到的是36 38 40,而另一个进程读到的是37 39 41。(也可以开启多个写进程去写,读者可自行测试)

我们在读写FIFO的时候都使用了open()函数,使用open函数的时候有一个注意事项,使用open打开FIFO文件的时候,read端会阻塞等待write端open打开文件,直到write进程也使用open打开FIFO的时候,read进程中的open才会返回,反过来也是一样。我们可以在open函数的前后分别打印一句话来测试,只有读端写端都open了FIFO,第二个printf()语句才能打印。实际上只要有一个write和一个read打开了FIFO,就可以,不管是同一个进程还是多个进程。

printf("hello open...\n");
int fd = open(argv[1], O_WRONLY);
printf("bye open...\n");

附:Makefile

通过一个makefile编译多个程序

.PHONY:all clean
CC=gcc
CFLAGS=-Wall -g
EXE=write_fifo read_fifo
all:$(EXE)
%.o:%.c
  $(CC) $(CFLAGS) -c $< -o $@
clean:
  -@rm -f *.o $(EXE)


相关文章
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
本文详细介绍了进程间通信(IPC)的六种主要方式:管道、信号、消息队列、共享内存、信号量和套接字。每种方式都有其特点和适用场景,如管道适用于父子进程间的通信,消息队列能传递结构化数据,共享内存提供高速数据交换,信号量用于同步控制,套接字支持跨网络通信。通过对比和分析,帮助读者理解并选择合适的IPC机制,以提高系统性能和可靠性。
2265 14
|
存储 Unix Linux
进程间通信方式-----管道通信
【10月更文挑战第29天】管道通信是一种重要的进程间通信机制,它为进程间的数据传输和同步提供了一种简单有效的方法。通过合理地使用管道通信,可以实现不同进程之间的协作,提高系统的整体性能和效率。
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
1101 20
|
消息中间件 存储 Linux
|
消息中间件 Linux API
Linux c/c++之IPC进程间通信
这篇文章详细介绍了Linux下C/C++进程间通信(IPC)的三种主要技术:共享内存、消息队列和信号量,包括它们的编程模型、API函数原型、优势与缺点,并通过示例代码展示了它们的创建、使用和管理方法。
550 0
Linux c/c++之IPC进程间通信
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
1605 5
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能
|
弹性计算 Linux 区块链
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
769 4
Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。

热门文章

最新文章