当前位置:首页 > 公众号精选 > wenzi嵌入式软件

概述

管道是 UNIX系统 IPC的最古老的形式,所有的UNIX系统都提供此种通信。所谓的管道,也就是内核里面的一串缓存,从管道的一段写入的数据,实际上是缓存在内核中的,令一端读取,也就是从内核中读取这段数据。对于管道传输的数据是无格式的流且大小受限。对于管道来说,也分为匿名管道和命名管道,其中命名管道也被叫做 FIFO,下面则分别阐述这两种管道。

匿名管道

默认情况下,在 Shell命令执行过程中,任何一个命令都有一个标准输入设备(键盘)、标准输出设备(显示器)和标准输出设备(显示器),使用管道"|"可以将两个命令连接起来,从而改变标准的输入输出方式,下面是在 Linux 端运行命令行的一个截图:

image-20210704161819420
上述命令中的意思也就是,将ls命令得到的结果作为 grep tags命令的输入。

image-20210704162803903
连接输入输出的中间设备即为一个管道文件,综上,也就是说使用管道可以将一个命令的输出作为另一个命令的输入(在运行的时候,一个命令将创建一个进程),而这种管道是临时的,命令执行完毕之后就会自动消失,这类管道称为无名管道

匿名管道例子

匿名管道在使用前要先创建,其函数的声明如下:

extern int pipe (int __pipedes[2]);
此函数的参数是一个整型数组,如果执行成功,pipe 将存储两个整型文件描述符于__pipedes[0]__pipedes[1]中,他们分别指向管道的两端。如果系统调用失败,则返回 -1。

读无名管道,该函数的声明如下:

extern ssize_t read (int __fd, void *__buf, size_t __nbytes);
第一个参数fd为打开的文件描述符,buf为读出数据的存储位置,nbytes为读取数据的大小,调用 read 函数将从 fd 指向的文件描述符指定的打开文件中宏读 n 字节到 buf 指向的缓冲区内。

如果试图向已经填满的管道写入,系统会自动阻塞。一个管道不能同时被两个进程打开。

extern ssize_ t write(int __fd, __const void *__buf, size_t __n);
从 buf指向的缓冲区中向管道中写入nbytes字节,且每次写入的内容都附件在管道的末端。

那要如何使用管道在两个进程之间通信呢,我们可以使用 fork()创建子进程,创建的子进程会复制父进程的文件描述符,这样就做到了两个进程各有两个fd[0]与fd[1],两个进程就可以通过各自的fd写入和读取同一个管道文件实现进程通信了,具体原理如下所示:

image-20210704170602297
具体的例子如下所示:

#include
#include
#include

int main(int argc, char *argv[])
{
    pid_t pid;
    int temp;
    int pipedes[2];
    char s[14] = "test message!";
    char d[14];

    if (pipe(pipedes) == -1// 创建管道
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    if (pid == fork() == -1)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    else if (pid == 0)      // 子进程
    {
        printf("now,write data to pipe\n");
        if (write(pipedes[1], s, 14) == -1)   // 写数据到管道
        {
            perror("write");
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("the written data is:%s\n",s);
            exit(EXIT_SUCESS);
        }
    }
    else if (pid > 0)     // 父进程
    {
        slepp(2);
        printf("now, read from pipe\n");
        if ((read(pipedes[0], d, 14)) == -1)
        {
            perror("read");
            exit(EXIT_FAILURE);
        }
        printf("the data from pipe is:%s\n",d);
    }
    return 0;
}
代码运行的结果如下所示:

image-20210704172243185

命名管道

命名管道又被称之为是 FIFO ,未命名的管道只能在两个相关的进程之间使用,而且这两个相关的进程还要又一个共同创建了他们的祖先进程,但是,通过 FIFO ,不相关的进程也能交换数据。

首先,介绍下是如何创建命名管道的:

extern int mkfifo (__const char *__path, __mode_t __mode);
mkfifo会根据参数建立特殊的有名管道文件,该文件必须不存在,而参数mode为该文件的权限。

下面是一个使用命名管道进行进程间通信的例子,例子分为两个程序,分别是读部分和写部分,首先看先往管道写数据的代码,代码如下所示:

#include  
#include  
#include  
#include  
#include  
#include  

int main() 

    int fd; 

    // FIFO file path 
    char * myfifo = "/tmp/myfifo"

    // Creating the named file(FIFO) 
    // mkfifo(, ) 
    mkfifo(myfifo, 0666); 

    char arr1[80], arr2[80]; 
    while (1
    { 
        // Open FIFO for write only 
        fd = open(myfifo, O_WRONLY); 
        printf("The fd is:%d\n",fd);

        // Take an input arr2ing from user. 
        // 80 is maximum length 
        fgets(arr2, 80stdin); 

        // Write the input arr2ing on FIFO 
        // and close it 
        write(fd, arr2, strlen(arr2) 1); 
        close(fd); 

        // Open FIFO for Read only 
        fd = open(myfifo, O_RDONLY); 

        // Read from FIFO 
        read(fd, arr1, sizeof(arr1)); 

        // Print the read message 
        printf("User2: %s", arr1); 
        close(fd); 
    } 
    return 0
}
然后是先往管道读数据的代码,代码如下所示:

#include  
#include  
#include  
#include  
#include  
#include  

int main() 

    int fd1; 

    // FIFO file path 
    char * myfifo = "/tmp/myfifo"

    char str1[80], str2[80]; 
    while (1
    { 
        // First open in read only and read 
        fd1 = open(myfifo,O_RDONLY); 
        printf("The fd is:%d\n",fd1);
        read(fd1, str1, 80); 

        // Print the read string and close 
        printf("User1: %s", str1); 
        close(fd1); 

        // Now open in write mode and write 
        // string taken from user. 
        fd1 = open(myfifo,O_WRONLY); 
        fgets(str2, 80stdin); 
        write(fd1, str2, strlen(str2) 1); 
        close(fd1); 
    } 
    return 0

下面是代码运行的一个结果:

image-20210706132916572
说明一下,就是说当运行 write程序的时候,会创建fifo文件,命名管道,然后,在 write文件中就执行open操作,但是,这里存在的一个问题就是,因为在运行 write程序的时候,没有进程打开读端,也就阻塞了 open函数的运行,只有运行read操作,以读的方式读取管道的数据,这样才能使得write中的open函数继续执行。

综上,也就是命名管道在进程中通信的一个例子。

小结

上述就是本次进程通信中关于管道的相关内容,其中就包括匿名管道以及命名管道,他们之间存在着差别吗,也各有各的应用,本次的分享就到这里啦~

你点的每个好看,我都认真当成了喜欢
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

设计工程师为了解决ISI问题,常常需要在链路损耗和均衡技术之间做出综合考虑。泰克的SDLA软件不仅可以模拟发送端的Tx EQ和接收端的Rx EQ,还能模拟传输链路的不同损耗。

关键字: 通信 示波器 测试测量

5G网络相较于4G网络,具有更高的数据传输速率,能够支持更高的峰值速率,理论上峰值传输速率可以达到10Gbit/s,这比4G网络快了大约10到100倍。

关键字: 5G 通信 4G网络

双系统将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对双系统的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 双系统 Windows Linux

泰克实时示波器支持TekExpressLVDS自动测量软件,涵盖LVDS时钟和数据的30多个测量项目,一键完成一致性测量。

关键字: 通信 示波器 测试测量

2024年2月26日,国际通信行业盛会MWC 24于西班牙巴塞罗那召开,全球通信及其相关供应链的顶尖企业荟聚一堂,展示移动通信领域的前沿研究成果,与国际行业同仁展开深入技术交流。三安集成作为射频前端整合解决方案服务提供商...

关键字: 三安集成 射频 通信

在意大利媒体对沃达丰的并购交易提出多种猜测之后,该公司2月28日发布声明称,正在就将沃达丰意大利公司(Vodafone Italy)出售给瑞士电信进行独家谈判,但尚未达成有约束力的协议。

关键字: 沃达丰 瑞士电信 通信 宽带

即将于2024年6月竣工交付的华为上海研发基地(青浦),不仅是上海市重点工程,也是长三角一体化示范区西岑科创中心的亮点项目。

关键字: 华为 通信 芯片

全球4G和5G的部署速度比商业服务的推进速度更快,6G预计到2030年也会到来,电信运营商如何以正确姿势迎接未来?

关键字: AI 通信 5G 6G

安装Linux操作系统并不复杂,下面是一个大致的步骤指南,以帮助您完成安装。1. 下载Linux发行版:首先,您需要从Linux发行版官方网站下载最新的ISO镜像文件。

关键字: Linux 操作系统 ISO镜像

计算机是由一堆硬件组成的,为了有限的控制这些硬件资源,于是就有了操作系统的产生,操作系统是软件子系统的一部分,是硬件基础上的第一层软件。

关键字: Linux 操作系统 计算机
关闭
关闭