Linux管道

2023-05-16

目录

1.管道概念

2.管道分类

        1.匿名管道

        1.基本实现与概念

        2.站在文件描述符角度-深度理解管道

        3.站在内核角度-管道本质

        4.管道读写规则

        5.管道属性设置与阻塞验证       

         6.管道特点(匿名)

        2.命名管道

        1.创建一个命名管道

        2.命名管道的打开规则 

 3.匿名管道与命名管道的区别


1.管道概念

        管道是Linux中的最古老的通信方式;

        我们把一个进程链接到另一个进程的一个数据流称为一个"管道";

2.管道分类

        1.匿名管道

        1.基本实现与概念

        头文件: #include <unistd.h>

        功能:创建一无名管道原型int pipe(int fd[2]);

        参数fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端返回值:成功返回0,失败返回错误代码

         通常用fork函数来共享管道;接下来我们来实现一下匿名管道的基本读写的实现:

                                                                不关闭描述符

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

int main(){
    int fd[2];
    int ret=pipe(fd);
    if(ret<0){
        perror("pipe");
        return 0;
    }
    pid_t pid=fork();
    if(pid<0){
        perror("fork");
        return 0;
    }else if(pid==0){
        //child
        //子进程进行接受
        char buf_read[1024]={0};
        read(fd[0],buf_read,sizeof(buf_read)-1);
        printf("The content is :%s\n",buf_read);
    }else{
        //father
        //父进程发送数据
        char buf_write[]="success!";
        write(fd[1],buf_write,strlen(buf_write));
        wait(NULL);
    }
    return 0;
}

                                                                运行结果

        我们可以看出来在父进程向管道写入信息,在子进程读取管道信息. 

                                                          关闭描述符

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

int main(){
    int fd[2];
    int ret=pipe(fd);
    if(ret<0){
        perror("pipe");
        return 0;
    }
    pid_t pid=fork();
    if(pid<0){
        perror("fork");
        return 0;
    }else if(pid==0){
        //child
        //子进程进行接受
        close(fd[1]);
        char buf_read[1024]={0};
        read(fd[0],buf_read,sizeof(buf_read)-1);
        printf("The content is :%s\n",buf_read);
    }else{
        //father
        //父进程发送数据
        close(fd[0]);
        char buf_write[]="success!";
        write(fd[1],buf_write,strlen(buf_write));
        wait(NULL);
    }
    return 0;
}

                                                        运行结果 

                我们可以看出依旧可以进行读写~原因是什么呢?

        2.站在文件描述符角度-深度理解管道

 

        首先父进程创建管道,系统默认打开三个文件:标准输入,标准输出,和标准错误;创建管道则有fd[0],fd[1];分别表示管道的读端和写端;

         然后父进程创建子进程,子进程拷贝父进程,也拷贝了管道信息;所以父子进程共享管道;

         父进程关闭读端,子进程关闭写端,但是管道是共享的,依旧可以进行信息交互;

        3.站在内核角度-管道本质

 看待管道,就如同看待文件一样!管道的使用和文件一致,迎合了“Linux一切皆文件思想”。

        4.管道读写规则

        当没有数据可读时O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。

        当管道满的时候O_NONBLOCK disable: write调用阻塞,直到有进程读走数据O_NONBLOCK enable:调用返回-1,errno值为EAGAIN如果所有管道写端对应的文件描述符被关闭,则read返回0   

        如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出

        当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。

        当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。

        5.管道属性设置与阻塞验证       

        fcntl函数原型:

#include<unistd.h>
#include<fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd ,struct flock* lock);

 (1)F_DUPFD

与dup函数功能一样,复制由fd指向的文件描述符,调用成功后返回新的文件描述符,与旧的文件描述符共同指向同一个文件。

(2)F_GETFD

读取文件描述符close-on-exec标志

(3)F_SETFD

将文件描述符close-on-exec标志设置为第三个参数arg的最后一位

(4)F_GETFL

获取文件打开方式的标志,标志值含义与open调用一致

(5)F_SETF

设置文件打开方式为arg指定方式

设置读端为非阻塞:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(){
    int fd[2];
    int ret=pipe(fd);
    if(ret<0){
        perror("pipe");
        return 0;
    }
    pid_t pid=fork();
    if(pid<0){
        perror("fork");
        return 0;
    }else if(pid==0){
        //child 
        //关闭写端
        //设置读端为非阻塞属性
        //读
        close(fd[1]);
        int flag=fcntl(fd[0],F_GETFL);
        fcntl(fd[0],F_SETFL,flag|O_NONBLOCK);
        char buf_read[1024]={0};
        ssize_t read_size=read(fd[0],buf_read,sizeof(buf_read)-1);
        printf("read_size:%ld\n",read_size);
        perror("read");

    }else{
        //father
        //关闭读端
        //写关闭/不关闭
        close(fd[0]);
        close(fd[1]);
    }
    while(1){
        sleep(1);
    }
    return 0;
}

                                                                        运行结果为:

 设置写端非阻塞:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(){
    int fd[2];
    int ret=pipe(fd);
    if(ret<0){
        perror("pipe");
        return 0;
    }
    pid_t pid=fork();
    if(pid<0){
        perror("fork");
        return 0;
    }else if(pid==0){
        //child
        //关闭子进程读端
        //设置子进程写段为非阻塞
        //子进程写
        close(fd[0]);
        int flag=fcntl(fd[1],F_GETFL);
        fcntl(fd[1],F_SETFL,flag|O_NONBLOCK);
        ssize_t write_size;
        while(1){
            write_size=write(fd[1],"a",1);
            if(write_size<0){
                break;
            }
        }
        printf("write_size:%ld\n",write_size);
    }else{
        //father
        //关闭父进程写端
        //关闭父进程读端/不关闭
        close(fd[1]);
        //close(fd[0]);
        while(1){
            sleep(1);
        }
    }
    return 0;
}

                                                运行结果:

         6.管道特点(匿名)

        只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;

        通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。

        管道提供流式服务一般而言,进程退出,管道释放,所以管道的生命周期随进程一般而言,内核会对管道操作进行同步与互斥管道是半双工的;

        数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;

        2.命名管道

        管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。

        如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。

        命名管道是一种特殊类型的文件

        1.创建一个命名管道

$ mkfifo pipe1

执行结果: 

也可以程序创建

函数原型:

#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char *filename,mode_t mode);

                                        代码如下: 

#include <stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
int main(){
    mkfifo("pipe2",0664);
    return 0;
}

                                        运行结果

        2.命名管道的打开规则 

        如果当前打开操作是为读而打开FIFO时

        O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO

        O_NONBLOCK enable:立刻返回成功如果当前打开操作是为写而打开FIFO时

        O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO 

        O_NONBLOCK enable:立刻返回失败,错误码为ENXIO                

 3.匿名管道与命名管道的区别

        匿名管道由pipe函数创建并打开。

        命名管道由mkfifo函数创建,打开用openFIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux管道 的相关文章

  • 如何在 Linux 中重新添加 unicode 字节顺序标记?

    我有一个相当大的 SQL 文件 它以 FFFE 的字节顺序标记开头 我使用 unicode 感知的 linux 分割工具将此文件分割成 100 000 行块 但是当将这些传递回窗口时 它确实not与第一个部分以外的任何部分一样 只是它具有
  • C++:Linux平台上的线程同步场景

    我正在为 Linux 平台实现多线程 C 程序 其中我需要类似于 WaitForMultipleObjects 的功能 在搜索解决方案时 我发现有一些文章描述了如何在 Linux 中实现 WaitForMultipleObjects 功能
  • 在 debian wheezy amd64 上安装 ia32-libs

    我正在使用 Debian 7 喘息 amd64 uname a Linux tzwm debian 3 2 0 4 amd64 1 SMP Debian 3 2 51 1 x86 64 GNU Linux 我想安装ia32 libs在我的
  • 如何在 Linux/OS X 上温和地终止 Firefox 进程

    我正在使用 Firefox 进行一些自动化操作 尽管我可以从 shell 打开 Firefox 窗口 但我无法正确终止它 如果我kill火狐进程与kill 3 or kill 2当我下次打开新的 Firefox 窗口时 命令会询问我是否要在
  • 计算 TCP 重传次数

    我想知道在LINUX中是否有一种方法可以计算一个流中发生的TCP重传的次数 无论是在客户端还是服务器端 好像netstat s解决了我的目的
  • 使用c在linux上分块读写

    我有一个 ASCII 文件 其中每一行都包含一个可变长度的记录 例如 Record 1 15 characters Record 2 200 characters Record 3 500 characters Record n X cha
  • 如何在perl中使用O_ASYNC和fcntl?

    我想使用 O ASYNC 选项 当管道可以读取时 SIGIO 的处理程序将运行 但以下代码不起作用 任何人都可以帮助我吗 bin env perl use Fcntl SIG IO sub print catch SIGIO n my fl
  • 比较linux中的两个未排序列表,列出第二个文件中的唯一项

    我有 2 个包含号码列表 电话号码 的文件 我正在寻找一种列出第二个文件中第一个文件中不存在的数字的方法 我尝试过各种方法 comm getting some weird sorting errors fgrep v x f second
  • 如何在特定的Java版本上运行应用程序?

    如何运行具有特定 Java 版本的应用程序 我安装了三个 Java 版本 myuser mysystem sudo update alternatives config java There are 3 choices for the al
  • Grep 递归和计数

    需要在具有大量子目录的目录中搜索文件内的字符串 我在用着 grep c r string here 我怎样才能找到总数量 如何仅输出至少具有一个实例的文件 使用 Bash 的进程替换 这给出了我认为是您想要的输出 如果不是 请澄清问题 gr
  • 如何回忆上一个 bash 命令的参数?

    Bash 有没有办法回忆上一个命令的参数 我通常这样做vi file c其次是gcc file c Bash 有没有办法回忆上一个命令的参数 您可以使用 or 调用上一个命令的最后一个参数 Also Alt can be used to r
  • 查找并删除超过 x 天的文件或文件夹

    我想删除超过 7 天的文件和文件夹 所以我尝试了 17 07 14 email protected cdn cgi l email protection find tmp mindepth 1 maxdepth 1 ctime 7 exec
  • 如何通过不同的接口路由 TCP/IP 响应?

    我有两台机器 每台机器都有两个有效的网络接口 一个以太网接口eth0和 tun tap 接口gr0 目标是使用接口在机器 A 上启动 TCP 连接gr0但然后让机器 B 的响应 ACK 等 通过以太网接口返回 eth0 因此 机器 A 发出
  • 如何使用 VSCode 调试 Linux 核心转储?

    我故意从我使用 VSCode 编写的 C 应用程序生成核心转储 我不知道如何调试核心转储 有没有人愿意分享这方面的经验 更新 我相信我现在已经可以使用了 我为核心文件创建了第二个调试配置 我需要添加指向生成的转储文件的 coreDumpPa
  • 在 vimrc 中切换匹配

    我的 vimrc 文件中有以下几行 hi ExtraWhitespace cterm NONE ctermbg green ctermfg green guibg green guifg green match ExtraWhitespac
  • Linux 中有没有一种轻量级的方法来获取当前进程数?

    我希望我的 基于 C C 的 程序显示一个数字指示器 指示本地系统上当前有多少个进程 将经常查询正在运行的进程数值 例如每秒一次 以更新我的显示 有没有一种轻量级的方法来获取该数字 显然我可以调用 ps ax wc l 但我不想强迫计算机生
  • 我可以在 Ubuntu 上使用 Homebrew 吗?

    我只是尝试使用 Homebrew 和 Linuxbrew 在我的 Ubuntu 服务器上安装软件包 但都失败了 这就是我尝试安装它们的方法 sudo apt get install build essential curl git m4 r
  • 通过名称获取进程ID

    我想在 Linux 下获得一个给定其名称的进程 ID 有没有一种简单的方法可以做到这一点 我还没有在 C 上找到任何可以轻松使用的东西 如果追求 易于使用 char buf 512 FILE cmd pipe popen pidof s p
  • 打印 STDOUT/STDERR 并将它们写入 Bash 中的文件?

    有没有办法让 Bash 将 STDOUT STDERR 重定向到文件 但仍然将它们打印到终端 这会将 STDOUT 和 STDERR 重定向到同一个文件 some command 2 gt 1 tee file log Example to
  • Linux 上的“软/硬 nofile”是什么意思

    当我尝试在RedHat EL5上安装软件时 我得到了错误 软 硬nofile的期望值是4096 而默认值是1024 我设法增加了这个数字 但我不知道参数是什么 他们指的是软链接和硬链接吗 我改变的方法是 a 修改 etc security

随机推荐

  • 无人机飞行控制实验平台

    无人机在研制过程中需要不断地进行飞行测试 xff0c 而测试的过程不是万无一失的 xff0c 飞行过程中发生任何错误都有可能会导致无人机的损毁或破坏 xff0c 更严重地甚至会造成外界伤害 基于此我们推出了无人机的三旋转自由度 3 DOF
  • ADS-B教学实验方案

    ADS B教学系统是为了让学生学习ADS B原理 ADS B系统组成 ADS B信号处理技术 可以通过ADS B教学系统进一步研究分析ADS B位置的精度 准确性 稳定性 实时性 xff0c 设计基于ADS B的空中碰撞告警系统 xff0c
  • ROS系列:工作空间及功能包创建

    前言 分享一下ROS开发的基础教程 xff0c 全部自己手敲 xff0c 希望能帮到正在学习的你 ROS在WIKI上也有教程 xff0c 个人觉得太过臃肿 xff0c 可以简化点 xff0c 毕竟大家都赶着投胎 xff0c 哈哈哈哈哈 一
  • java UDP DatagramSocket接收不到数据

    今天联系这个通信 xff0c 接收端总是接收不到数据 xff01 排除代码本身有可能出现的错误 xff0c 比如地址 xff0c 数据宝包 我称它为数据宝宝 xff09 等等自己粗心的错误后还是不行 xff0c 我查看各种方法 xff0c
  • Python与爬虫有什么关系?

    爬虫一般是指网络资源的获取 xff0c 因为python的脚本特征 xff0c Python易于配置 xff0c 对字符的处理也非常灵活 xff0c 加上python有丰富的网络抓取模块 xff0c 所以两者经常联系在一起 接下来我们可以详
  • C++中struct和class的区别

    1 C 43 43 中struct和class的区别 C 43 43 中的struct其实是为了与C的兼容性而留下来的 C 43 43 的struct和class其实大部分都是相同的用法 xff0c 基本上可以用class做的事都可以用st
  • L298N驱动步进电机,有stm32代码亲测可用

    1 1 步进电机相关概念 相数 xff1a 产生不同对极N S磁场的激磁线圈对数 xff0c 常用 m 表示 例如 xff1a 二相四线电机 xff0c 就有两对极N S磁场的激磁线圈 xff0c 四个线圈 上图可知 xff0c A 43
  • C++成员初始化

    C 43 43 成员分为 xff1a 一般变量 xff0c const修饰变量 xff0c 引用类型成员 xff0c static成员 xff0c const staic成员 同static const xff0c 自定义类型对象 clas
  • HTTP协议解析

    目录 1 HTTP协议的概念 2 HTTP协议格式 3 HTTPS 1 HTTP协议的概念 在我们之前学习网络的过程中 xff0c 我们知道了目前主流网络分层模型共分为5层 xff0c 分别是物理层 xff0c 数据链路层 xff0c 网络
  • cmake编译opencv开源项目报错问题

    最近使用cmake在编译一个配置了opencv环境的c 43 43 开源项目时遇到如下问题 CMake Warning at D opencv4 OpenCVConfig cmake 176 message Found OpenCV Win
  • Ubuntu系统换源

    简单介绍一下源 xff0c 源就是一个大仓库 xff08 类似应用商店 xff09 xff0c 系统下载软件需要从这个仓库下载 xff0c 因为Ubuntu默认源是国外的 xff0c 所以在下载东西的时候会出现下载速度很慢的情况 xff0c
  • 字符串的简单介绍和字符串的大小比较

    以前就写过一篇关于String的文章 xff0c 今天再来写一篇 xff0c 更加深入了解一下String类 x1f550 1 String类的定义 x1f551 2 String类的创建 x1f552 3 字符串的大小比较 1 之前在C语
  • 数据结构1

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
  • 洛谷P5740 【深基7.例9】最厉害的学生

    题目描述 现有 N N le 1000 N N 1000 名同学参加了期末考试 xff0c 并且获得了每名同学的信息 xff1a 姓名 xff08 不超过 8 个字符的仅有英文小写字母的字符串 xff09 语文 数学 英语成绩 xff08
  • C语言创建链表并输出

    代码如下 define CRT SECURE NO WARNINGS include lt stdio h gt include lt assert h gt include lt string h gt include lt stdlib
  • 游戏搬砖是什么意思?

    网络游戏搬砖是指在各网络游戏中 xff0c 玩家把花大量时间 精力赚的钱转手为游戏买各种东西 搬砖原本是一个汉语词语 xff0c 意思是原指搬运砖块 xff0c 在网络语中 xff0c 搬砖引申为工作辛苦 重复机械 赚钱不多的工作 在一些方
  • C语言实现扫雷游戏

    话不多说直接淦代码 代码都有详细注释 define CRT SECURE NO WARNINGS include lt stdio h gt include lt time h gt include lt stdlib h gt inclu
  • C语言用栈实现队列(数据结构)

    1 首先需要两个栈来模拟队列的出队和入队 2 假设入队1 2 3 4 如果要出队则不能直接出栈 需要进行数据的搬移 先把s1的数据全部放入s2中 然后再在s2出栈 gt 整个队列出队 3 如果再要入队则将入队元素放入s1 若要出队则出栈s2
  • Linux权限理解(详细详细)

    目录 一 权限的概念 二 Linux权限管理 1 文件访问者的分类 xff08 人 xff09 2 文件类型和访问权限 xff08 事物属性 xff09 3 文件权限值的表示方法 1 字符表示 2 8进制数字表示法 4 文件访问权限的相关设
  • Linux管道

    目录 1 管道概念 2 管道分类 1 匿名管道 1 基本实现与概念 2 站在文件描述符角度 深度理解管道 3 站在内核角度 管道本质 4 管道读写规则 5 管道属性设置与阻塞验证 6 管道特点 匿名 2 命名管道 1 创建一个命名管道 2