Linux多进程(二)进程通信方式一 管道

这篇具有很好参考价值的文章主要介绍了Linux多进程(二)进程通信方式一 管道。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

管道的是进程间通信(IPC - InterProcess Communication)的一种方式,管道的本质其实就是内核中的一块内存(或者叫内核缓冲区),这块缓冲区中的数据存储在一个环形队列中,因为管道在内核里边,因此我们不能直接对其进行任何操作。

因为管道数据是通过队列来维护的,我们先来分析一个管道中数据的特点:

  • 管道对应的内核缓冲区大小是固定的,默认为4k(也就是队列最大能存储4k数据)
  • 管道分为两部分:读端和写端(队列的两端),数据从写端进入管道,从读端流出管道
  • 管道中的数据只能读一次,做一次读操作之后数据也就没有了(读数据相当于出队列)
  • 管道是单工的:数据只能单向流动, 数据从写端流向读端
  • 对管道的操作(读、写)默认是阻塞的

一、匿名管道

匿名管道是管道的一种,既然是匿名也就是说这个管道没有名字,但其本质是不变的,就是位于内核中的一块内存,匿名管道拥有上面介绍的管道的所有特性。

pipe 函数用于创建一个管道,以实现进程间通信。

#include <unistd.h>

int pipe(int fd[2]);

管道容量的大小默认是65536字节。我们可以使用fcntl函数来修改管道容量。

下面举一个在多进程程序中管道通信的例子:

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main()
{
    int pipefd[2];
    char buf[1024];

    // 创建管道
    if (pipe(pipefd) == -1)
    {
        perror("pipe error! \n");
        return 1;
    }

    for (int i = 0; i < 8; i++)
    {
        // 创建子进程
        pid_t pid = fork();

        if (pid == -1)
        {
            perror("fork error!\n");
            return 1;
        }
        else if (pid == 0)
        {
            // 子进程关闭写端
            close(pipefd[1]);
            // 从管道读取数据
            memset(buf, 0, 1024);
            read(pipefd[0], buf, sizeof(buf));
            // 打印数据
            printf("pid = %d :Child process received: %s\n", getpid(), buf);
            // 子进程关闭读取端
            close(pipefd[0]);
            // 子进程直接break,以免创建更多的子进程
            break;
        }
    }

    if (getpid() != 0)
    {
        // 父进程关闭读取端
        close(pipefd[0]);
        // 向管道写入数据
        const char *message = "Hello from parent process";
        for (int i = 0; i < 8; i++)
        {
            write(pipefd[1], message, strlen(message));
            sleep(1);
        }
        // 在所有数据都写入后再关闭写入端
        close(pipefd[1]);
    }

    return 0;
}

生成了八个子进程,八个子进程阻塞在read处,等待父进程的消息,父进程发了八次消息,每次间隔1秒。看一下仿真
Linux多进程(二)进程通信方式一 管道,Linux,linux,服务器,算法

二、有名管道

有名管道拥有管道的所有特性,之所以称之为有名是因为管道在磁盘上有实体文件, 文件类型为p ,有名管道文件大小永远为0,因为有名管道也是将数据存储到内存的缓冲区中,打开这个磁盘上的管道文件就可以得到操作有名管道的文件描述符,通过文件描述符读写管道存储在内核中的数据。

有名管道也可以称为 fifo (first in first out),使用有名管道既可以进行有血缘关系的进程间通信,也可以进行没有血缘关系的进程间通信。创建有名管道的方式有两种,一种是通过命令,一种是通过函数。

2.1、创建有名管道

通过命令

mkfifo 有名管道的名字

通过函数

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);
  • pathname: 要创建的有名管道的名字
  • mode: 文件的操作权限, 和open()的第三个参数一个作用,最终权限: (mode & ~umask)
  • 返回值:创建成功返回 0,失败返回 -1

2.2、进程间通信

不管是有血缘关系还是没有血缘关系,使用有名管道实现进程间通信的方式是相同的,就是在两个进程中分别以读、写的方式打开磁盘上的管道文件,得到用于读管道、写管道的文件描述符,就可以调用对应的read()、write()函数进行读写操作了。

有名管道操作需要通过 open() 操作得到读写管道的文件描述符,如果只是读端打开了或者只是写端打开了,进程会阻塞在这里不会向下执行,直到在另一个进程中将管道的对端打开。

写管道的进程

#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    // 1. 创建有名管道文件
    int ret = mkfifo("./testfifo", 0664);
    if(ret == -1)
    {
        perror("mkfifo");
        exit(0);
    }
    printf("管道文件创建成功...\n");

    // 2. 打开管道文件
    int wfd = open("./testfifo", O_WRONLY);
    if(wfd == -1)
    {
        perror("open");
        exit(0);
    }
    printf("以只写的方式打开文件成功...\n");

    // 3. 循环写管道
    int i = 0;
    while(i<100)
    {
        char buf[1024];
        sprintf(buf, "hello, fifo, 我在写管道...%d\n", i);
        write(wfd, buf, strlen(buf));
        i++;
        sleep(1);
    }
    close(wfd);

    return 0;
}

读管道的进程

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

int main()
{
    // 1. 打开管道文件
    int rfd = open("./testfifo", O_RDONLY);
    if(rfd == -1)
    {
        perror("open");
        exit(0);
    }
    printf("以只读的方式打开文件成功...\n");

    // 2. 循环读管道
    while(1)
    {
        char buf[1024];
        memset(buf, 0, sizeof(buf));
        // 读是阻塞的, 如果管道中没有数据, read自动阻塞
        int len = read(rfd, buf, sizeof(buf));
        printf("读出的数据: %s\n", buf);
        if(len == 0)
        {
            // 写端关闭了, read解除阻塞返回0
            printf("管道的写端已经关闭, 拜拜...\n");
            break;
        }

    }
    close(rfd);

    return 0;
}

仿真结果

Linux多进程(二)进程通信方式一 管道,Linux,linux,服务器,算法文章来源地址https://www.toymoban.com/news/detail-861672.html

到了这里,关于Linux多进程(二)进程通信方式一 管道的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】进程通信之匿名管道通信

    我们往往需要多个进程协同,共同完成一些事情。 数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。

    2024年04月14日
    浏览(26)
  • Linux——进程间通信&&管道

    📘北尘_ :个人主页 🌎个人专栏 :《Linux操作系统》《经典算法试题 》《C++》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 数据传输:一个进程需要把他的数据传给另外一个进程。 资源共享:多个进程之间共享同样的资源。 通知事件:一个进程需要向另一个或一组

    2024年04月09日
    浏览(18)
  • linux——进程间通信——管道

     ✅1主页::我的代码爱吃辣 📃2知识讲解:Linux——进程间通信——管道通信 ☂️3开发环境:Centos7 💬4前言:进程间通信(InterProcess Communication,IPC)是指在不同进程之间传播或交换信息。 目录 一.什么是进程间通信 二.进程间通信目的  三.进程间通信发展 四.什么是管道

    2024年02月08日
    浏览(24)
  • Linux——进程间通信(管道)

    目录 进程通信的目的 管道 见见猪跑(举个例子) 文件描述符fd与管道的关系(深度理解管道) 什么是管道?  匿名管道 pipe函数概述 父子进程通信时与文件描述符的关系图(理解pipe函数的关键) pipe函数的使用  管道读写规则 管道的大小 自测  使用man 7 pipe查看 使用ulimit -a查看 管

    2024年02月03日
    浏览(70)
  • 【Linux】进程通信 — 管道

    从本章开始,我们开始学习进程通信相关的知识,本章将来详细探讨一下管道,学习匿名管道和命名管道的原理和代码实现等相关操作。目标已经确定,接下来就要搬好小板凳,准备开讲了…🙆🙆🙆🙆 在我们之前的学习中,我们知道进程是具独立性的。但是不要以为进程

    2024年02月16日
    浏览(19)
  • Linux——进程间通信、管道

    进程间的通信就是 在不同进程之间传播或交换信息。 举个例子: 古时,两军交战不斩来使; 因为两军互相是独立的,所以使节就是两军之间传话的进行传话的; 而在OS中,进程之间也是相互独立的,但某项工作并不是一个进程就可以完成,而是多个进程之间相互协助完成;

    2024年02月22日
    浏览(23)
  • Linux进程通信:无名管道

    (1)数据传输:进程间数据传输; (2)通知事件:一个进程向另一个或一组进程发送消息,通知某个事件的发生(如子进程终止时需通知父进程); (3)资源共享:多个进程共享资源,需要内核提供同步互斥机制; (4)进程控制:某进程需要控制另一个进程的执行(如

    2023年04月24日
    浏览(34)
  • [Linux]进程间通信--管道

    数据传输:一个进程需要将它的数据发送给另一个进程 。 资源共享:多个进程之间共享同样的资源。 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。 进程控制:有些进程希望完全控制另一个进程的执

    2024年02月09日
    浏览(20)
  • 【Linux】进程间通信(匿名管道 & 命名管道)-- 详解

    如何理解进程间通信? 进程具有独立性,所以进程想要通信难度是比较大的,成本高。 在日常生活中,通信的本质是传递信息,但站在程序员角度来看, 进程间通信的本质:让不同的进程看到同一份资源(内存空间) 。 进程间通信就是进程之间互相传递数据,那么进程间

    2024年04月28日
    浏览(21)
  • 【Linux】进程间通信——进程间通信的介绍和分类、管道、匿名管道、命名管道、匿名管道与命名管道的区别

      进程间通信(IPC,Interprocess communication)是一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息。这使得一个程序能够在同一时间里处理许多用户的要求。因为即使只有一个用户发出要求,也可能导致一个操作系统中

    2024年02月05日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包