Linux进程通信:无名管道

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

进程通信目的:

(1)数据传输:进程间数据传输;

(2)通知事件:一个进程向另一个或一组进程发送消息,通知某个事件的发生(如子进程终止时需通知父进程);

(3)资源共享:多个进程共享资源,需要内核提供同步互斥机制;

(4)进程控制:某进程需要控制另一个进程的执行(如Debug进程),此时控制进程需要拦截另一个进程的所有陷入、异常、状态等。

进行通信分类及方式:

Linux进程通信:无名管道


无名管道

特点:(1)半双工。数据同一时刻只能单向传输;

           (2)数据从管道一端写入,另一端读出;

           (3)写入管道的数据遵循先进先出;

           (4)管道非普通文件,不属于某个文件系统,只存在于内存;

           (5)无名管道只能在具有公共祖先的进程(父子进程、兄弟进程等)之间使用


(1)pipe函数:创建无名管道

#include<unistd.h>

int pipe(int pipefd[2]);
/*
功能:
    创建无名管道。
参数:
    pipefd:int型数组的首地址,存放了管道文件描述符pipefd[0]、pipefd[1]。
            pipefd[0]用于读管道,pipefd[1]用于写管道。
            一般的文件I/O函数都可用来操作管道(lseek除外)。
返回值:
    成功:0
    失败:-1
*/

pipe示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int test() {
    int fds[2];  // fds[0]用于读管道,fds[1]用于写管道
    int ret = -1;

    // 创建一个无名管道
    ret = pipe(fds);
    if (-1 == ret) {
        perror("pipe");
        return 1;
    }

    printf("读管道的文件描述符:%d, 写管道的文件描述符:%d\n", fds[0], fds[1]);

    // 关闭文件描述符
    close(fds[0]);
    close(fds[1]);
    return 0;
}

运行结果:

Linux进程通信:无名管道


(2)父子进程使用无名管道通信原理:

Linux进程通信:无名管道

a)需要在fork之前创建无名管道,然后子进程也有自己的读写管道描述符关联无名管道;

b)父进程给子进程发消息:父进程写管道、子进程读管道;需要关闭父进程的读端文件描述符(fds[0])、子进程的写端文件描述符(fds[1])。 反之类似。

c)管道默认为阻塞,读不到内容则阻塞等待有内容可读;可设置为非阻塞。


(3)管道读写特性:

case 1:

        a)若写端打开,管道中无数据,读端进程会阻塞;

        b)若写端打开,管道中有数据,读端进程将数据读出,下次若无数据可读则阻塞;

case 2:

        若写端关闭,读端进程读取全部内容后,返回0;

case 3:

        若读端打开,管道被写满,则写端进程阻塞;

case 4:

        若读端关闭,写端进程收到一个信号,然后退出。

查看管道大小:

Linux进程通信:无名管道


(4)父子进程使用无名管道通信示例:

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

#define SIZE 64

int main(int argc, const char* argv[]) {

    int ret = -1;
    int fds[2];
    pid_t pid = -1;
    char buf[SIZE];

    // 1. 创建无名管道
    ret = pipe(fds);
    if (-1 == ret) {
        perror("pipe");
        return 1;
    }

    // 2. 创建子进程。需要在创建无名管道之后
    pid = fork();
    if (-1 == pid) {
        perror("fork");
        return 1;
    }

    // 子进程 读管道
    if (0 == pid) {
        close(fds[1]);  // 关闭写端

        ret = read(fds[0], buf, SIZE); // 读管道
        if (ret < 0) {
            perror("read");
            exit(-1);
        }

        printf("子进程读到的内容:%s\n", buf);

        close(fds[0]);  // 关闭读端
        exit(0); // 子进程退出
    }

    // 父进程 写管道
    close(fds[0]); // 关闭读端

    ret = write(fds[1], "ABCDEFG", 7);  // 写管道
    if (-1 == ret) {
        perror("write");
        return 1;
    }
    printf("父进程写了%d字节.\n", ret);
    close(fds[1]);  // 关闭写端

    return 0;
}

运行结果:

Linux进程通信:无名管道


(5)fpathconf函数:查看管道缓冲区

#include<unistd.h>

long fpathconf(int fd, int name);
/*
功能:
    通过name查看管道缓冲区的不同属性
参数:
    fd:读端或写端文件描述符
    name:
        _PC_PIPE_BUF:查看管道缓冲区大小
        _PC_NAME_MAX:文件名字节数上限
返回值:
    成功:属性值
    失败:-1
*/

fpathconf示例:

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

int main(int argc, const char* argv[]) {

    int fds[2];
    int ret = -1;

    ret = pipe(fds);
    if (-1 == ret) {
        perror("pipe");
        return 1;
    }

    printf("读端缓冲区大小:%ld,\n写端缓冲区大小:%ld,\n读端文件名字节数上限:%ld,\n写端文件名字节数上限:%ld\n",
        fpathconf(fds[0], _PC_PIPE_BUF), fpathconf(fds[1], _PC_PIPE_BUF),
        fpathconf(fds[0], _PC_NAME_MAX), fpathconf(fds[1], _PC_NAME_MAX));

    return 0;
}

运行结果:

Linux进程通信:无名管道


(6)管道读端缓冲区设置为非阻塞的方法:

// 获取读端缓冲区原先的状态标记flags 
int flags = fcntl(fd[0], F_GETFL); 

// 设置新状态标记flags加入非阻塞状态
flags |= O_NONBLOCK;

// 给读端缓冲区设置新状态标记
fcntl(fd[0], F_SETFL, flags);

读端设置为非阻塞,若无数据,读进程直接返回-1.

读端以非阻塞的方式读管道示例:

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

#define SIZE 64

int main(int argc, const char* argv[]) {

    int ret = -1;
    int fds[2];
    pid_t pid = -1;
    char buf[SIZE];

    // 1. 创建无名管道
    ret = pipe(fds);
    if (-1 == ret) {
        perror("pipe");
        return 1;
    }

    // 2. 创建子进程。需要在创建无名管道之后
    pid = fork();
    if (-1 == pid) {
        perror("fork");
        return 1;
    }

    // 子进程 读管道
    if (0 == pid) {
        close(fds[1]);  // 关闭写端

        /*设置读端非阻塞*/
        ret = fcntl(fds[0], F_GETFL);  // 获取读端缓冲区状态
        ret |= O_NONBLOCK; //将读端缓冲区加入非阻塞状态
        fcntl(fds[0], F_SETFL, ret); // 将新状态设置进入

        ret = read(fds[0], buf, SIZE); // 读管道
        if (ret < 0) {
            perror("read");
            exit(-1);
        }

        printf("子进程读到的内容:%s\n", buf);

        close(fds[0]);  // 关闭读端
        exit(0); // 子进程退出
    }

    // 父进程 写管道
    sleep(1);
    close(fds[0]); // 关闭读端

    ret = write(fds[1], "ABCDEFG", 7);  // 写管道
    if (-1 == ret) {
        perror("write");
        return 1;
    }
    printf("父进程写了%d字节.\n", ret);
    close(fds[1]);  // 关闭写端

    return 0;
}

运行结果:

Linux进程通信:无名管道文章来源地址https://www.toymoban.com/news/detail-423587.html

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

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

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

相关文章

  • 【Linux】进程间通信(匿名管道 & 命名管道)-- 详解

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

    2024年04月28日
    浏览(33)
  • 【Linux】进程通信 — 管道

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

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

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

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

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

    2024年02月08日
    浏览(33)
  • [Linux]进程间通信--管道

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

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

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

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

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

    2024年02月22日
    浏览(29)
  • Linux多进程(二)进程通信方式一 管道

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

    2024年04月29日
    浏览(23)
  • Linux之进程间通信(管道)

    目录 一、进程间通信 1、进程间通信的概念 2、进程间通信的目的 3、进程间通信的分类 二、管道 1、管道基本介绍 2、匿名管道 3、命名管道 什么是进程间通信? 我们在学习了进程的相关知识后,知道,进程的运行是具有独立性的,每个进程都有自己独立的PCB,也都有只属于

    2024年01月22日
    浏览(14)
  • 【Linux】进程间通信 -- 命名管道

    在管道的通信中,除了 匿名管道 ,还有一个 命名管道 。 匿名管道只支持具有 “亲戚关系” 的进程间通信,而命名管道就可以支持不同的,任意的进程通信。 那就下来就开始我们今天的学习。 匿名管道的两种使用方式: 指令的 \\\' | \\\' 和pipe()函数 命名管道也有两种使用方式

    2023年04月20日
    浏览(22)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包