【linux】dup文件描述符复制函数和管道详解

目录

一、文件描述符复制

1、dup函数(复制文件描述符)

​编辑 2、dup2函数(复制文件描述符)

​编辑 二、无名管道pipe

1、概述 

2、无名管道的创建

 3、无名管道读写的特点

 4、无名管道ps -A | grep bash实现

 三、有名管道FIFO(命名管道)

1、概述 

2、创建有名管道 mkfifo

3、有名管道读写的特点


一、文件描述符复制

        让新的文件描述符 指向 旧的文件描述符。(新旧文件描述符指向同一个文件) 使用的函数dup、dup2。

1、dup函数(复制文件描述符)

#include<unistd.h>

int dup(int oldfd);

        dup函数的功能:从系统中寻找最小可用的文件描述符 作为oldfd的副本。 新文件描述符 通过dup的返回值返回。

 2、dup2函数(复制文件描述符)

        #include<unistd.h>

        int dup2(int oldfd, int newfd);  

dup2的功能:将newfd作为oldfd的副本。 如果newfd事先存在 dup2会先close(newfd),然后将newfd作为oldfd的副本。 

 二、无名管道pipe

1、概述 

         管道(pipe)又称无名管道。 无名管道是一种特殊类型的文件,在应用层体现为 两个打开的文件描述符(读端和写端)。

管道的特点:

  1. 半双工,数据在同一时刻只能在一个方向上流动。
  2. 数据只能从管道的一端写入,从另一端读出
  3. 写入管道中的数据遵循先入先出的规则。
  4. 管道所传送的数据是无格式的,这要求管道的读出方与写入方必须事先约定好数据 的格式, 如多少字节算一个消息等。
  5. 管道不是普通的文件,不属于某个文件系统,其只存在于内存
  6. 管道在内存中对应一个缓冲区。不同的系统其大小不一定相同。
  7. 从管道读数据是一次性操作,数据一旦被读走,它就从管道中被抛弃,释放空间以便写更多的数据。
  8. 管道没有名字,只能在具有公共祖先的进程之间使用 

2、无名管道的创建

        #include<unistd.h>

        int pipe(int filedes[2]);

功能:经由参数filedes返回两个文件描述符

参数: filedes为int型数组的首地址,其存放了管道的文件描述符fd[0]、fd[1]。 filedes[0]为读而打开,filedes[1]为写而打开管道,filedes[0]的输出是filedes[1]的输 入。

返回值: 成功:返回 0 失败:返回-1

注意:在使用无名管道的时候 必须事先确定,谁发,谁收的问题。一旦确定不可更改。

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
    //创建一个无名管道
    int fd[2];
    pipe(fd);
    //创建一个子进程
    //父进程发 子进程收
    pid_t pid=fork();
    if(pid==0)//子进程
    {
        //子进程的写端无意义(可以事先关闭)
        close(fd[1]);
        //子进程接收父进程消息
        unsigned char buf[128]="";
        printf("子进程%d正在等待父进程的消息\n", getpid());
        read(fd[0],buf,sizeof(buf));
        printf("子进程%d读到的消息为:%s\n", getpid(), buf);
        //子进程读完数据 应该关闭读端
        close(fd[0]);
        //显示退出
        _exit(-1);
    }
    if(pid>0) //父进程
    {
        //父进程的读端无意义(可以事先关闭)
        close(fd[0]);
        //写端写入数据
        printf("3秒后父进程%d写入数据hello pipe\n",getpid());
        sleep(3);
        write(fd[1],"hello pipe",strlen("hello pipe"));
        printf("父进程:%d完成写入\n", getpid());
        //通信完成 应该关闭写端
        close(fd[0]);
        //等待子进程退出
        wait(NULL);
    }
    return 0;
}

 3、无名管道读写的特点

1、默认用read函数从管道中读数据是阻塞的。

2、调用write函数向管道里写数据,当缓冲区已满时write也会阻塞。

3、通信过程中,读端口全部关闭后,写进程向管道内写数据时,写进程会(收 到SIGPIPE信号)退出。 

 4、无名管道ps -A | grep bash实现

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
    //创建一个无名管道
    int fd[2];
    pipe(fd);
    //创建两个子进程
    int i=0; 
    for(i=0;i<2;i++)
    {
        pid_t pid=fork();
        if(pid==0)
            break;//防止子进程继续创建子进程
    }
    if(i==0)//子进程1
    {
        //ps ‐A 写端
        close(fd[0]);
        //1作为fd[1]的副本
        dup2(fd[1],1);
        //执行ps ‐A
        execlp("ps","ps","-A",NULL);
        _exit(-1);
    }
    else if(i==1)//子进程2
    {
        //grep bash 读端
        close(fd[1]);
        //0作为fd[0]的副本
        dup2(fd[0],0);
        //执行grep bash
        execlp("grep","grep","bash",NULL);
    }
    if(i==2) //父进程
    {
        //关闭管道读写端
        close(fd[0]);
        close(fd[1]);
        while(1)
        {
            pid_t pid=waitpid(-1,NULL,WNOHANG);
            if(pid>0)
                printf("子进程%d退出了\n", pid);
            else if(pid==0)
                continue;
            else if(pid<0)
                break;
        }
    }
    return 0;
}

 三、有名管道FIFO(命名管道)

1、概述 

         主要用于没有血缘关系的进程间通信。

 

 特点:

  1. 半双工,数据在同一时刻只能在一个方向上流动。
  2. 写入FIFO中的数据遵循先入先出的规则。
  3. FIFO所传送的数据是无格式的,这要求FIFO的读出方与写入方必须事先 约定好数据的格式,如多少字节算一个消息等。
  4. FIFO在文件系统中作为一个特殊的文件而存在,但FIFO中的内容存放在内存中。
  5. 管道在内存中对应一个缓冲区。不同的系统其大小不一定相同
  6. 从FIFO读数据是一次性操作,数据一旦被读,它就从FIFO中被抛弃,释 放空间以便写更多的数据。
  7. 当使用FIFO的进程退出后,FIFO文件将继续保存在文件系统中以便以后使用。
  8. FIFO有名字不相关的进程可以通过打开命名管道进 行通信(重要)

2、创建有名管道 mkfifo

FIFO文件的创建

        #include<sys/type.h>

        #include<sys/stat.h>

        int mkfifo( const char *pathname, mode_t mode);

参数:

pathname:FIFO的路径名+文件名。

mode:mode_t类型的权限描述符。

返回值: 成功:返回 0 失败:如果文件已经存在,则会出错且返回-1

 fifo_write.c:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
    //创建有名管道(确保两个进程识别相同目录)
    mkfifo("my_fifo",0666);
    //open以写的方式的打开 有名管道(阻塞 到 对方 以读的方式打开)
    int fp=open("my_fifo",O_WRONLY);
    if(fp<0)
    {
        perror("open");
        return 0;
    }
    printf("写端open成功\n");
    while(1)
    {
        //获取键盘输入
        unsigned char buf[128]="";
        printf("请输入需要发送的数据:");
        fgets(buf,sizeof(buf),stdin);
        buf[strlen(buf)-1]=0;
        //发送数据
        write(fp,buf,sizeof(buf));
        //退出循环
        if(strcmp(buf,"Bye")==0)
            break;
    }
    close(fp);
}

 fifo.read.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <string.h>
int main()
{
    //创建有名管道(确保两个进程识别相同目录)
    mkfifo("my_fifo",0666);
    //open以读的方式的打开 有名管道(阻塞 到 对方 以写的方式打开)
    int fp=open("my_fifo",O_RDONLY);
    if(fp<0)
    {
        perror("open");
        return 0;
    }
    printf("读端open成功\n");
    //循环的读取数据
    while(1)
    {
        //接收数据
        unsigned char buf[128]="";
        read(fp,buf,sizeof(buf));
        printf("收到数据:%s\n", buf);
        //退出循环
        if(strcmp(buf,"Bye")==0)
            break;
    }
    close(fp);
}

 

3、有名管道读写的特点

阻塞方式打开管道:

1、open以只方式打开FIFO时,要阻塞到某个进程为而打开此FIFO

2、open以只方式打开FIFO时,要阻塞到某个进程为而打开此FIFO。

3、open以只读、只写方式打开FIFO时会阻塞,调用read函数从FIFO里读数据时read也会阻塞

4、通信过程中若写进程先退出了,则调用read函数从FIFO里读数据时不阻塞;若写进程又 重新运行,则调用read函数从FIFO里读数据时又恢复阻塞

5、通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程也会(收到 SIGPIPE信号)退出

6、调用write函数向FIFO里写数据,当缓冲区已满时write也会阻塞

 非阻塞方式打开管道:

1、先以只读方式打开:如果没有进程已经为写而打开一个FIFO, 只读open成功,并且 open不阻塞

2、先以只写方式打开:如果没有进程已经为读而打开一个FIFO,只写open 将出错返回-1

3、read、write读写命名管道中读数据时不阻塞

4、通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程也会(收到 SIGPIPE信号)退出

注意: open函数以可读可写方式打开FIFO文件时的特点:

        1、open不阻塞

        2、调用read函数从FIFO里读数据时read会阻塞

        3、调用write函数向FIFO里写数据,当缓冲区已满时write也会阻塞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/730505.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

没有超头、最低价的视频号618战况如何?有何趋势变化?| 视频号618观察

转眼618大促已接近尾声&#xff0c;今年的你有剁手哪些好物吗&#xff1f;对618的整体感觉又是如何呢&#xff1f; 这是12年来&#xff0c;第一个电商平台没有预售付定金的618&#xff0c;当然或许此后的双11、每一次大促也将逐渐回归传统&#xff0c;回归本质。 而对于视频号来…

普通变频器位置闭环控制(S7-1200PLC工艺对象模拟量轴)

1、S7-1200PLC控制V90总线伺服通过工艺对象实现定位控制 S7-1200PLC和V90总线伺服通过工艺对象实现定位控制(标准报文3应用)_1200报文3控制v90-CSDN博客文章浏览阅读182次。V90伺服驱动器调试软件SINAMICS V-ASSISTANT Commissioning tool下载地址如下:西门子官网选型|资料CS…

linux下的进程通讯

一. 实验内容 1&#xff0e;编写一个程序&#xff0c;实现在两个进程之间运用管道进行通讯。程序中创建一个子进程&#xff0c;然后父、子进程各自独立运行。父进程不断地在标准输入设备上读入小写字母&#xff0c;写入管道。子进程不断地从管道中读取字符&#xff0c;转换为大…

Qt坐标系统

目录 概述 渲染 逻辑表示 锯齿绘制 坐标转换 模拟时钟示例 Window-Viewport转换 概述 坐标系统由QPainter类控制。与QPaintDevice和QPaintEngine类一起&#xff0c;QPainter构成了Qt绘画系统的基础。QPainter用于执行绘制操作&#xff0c;QPaintDevice是一个二维空间的抽…

10地!2024年一级造价师报名通知发布!

各位考生注意&#xff0c;西藏、四川、江西、新疆&#xff0c;辽宁、江苏、云南、新疆兵团、海南10个地区已经发布了关于2024年度一级造价工程师职业资格考试报名工作的通知&#xff1a; 浙江 辽宁 江苏 云南 报名时间&#xff1a;6月28日9:00—7月8日17:00&#xff1b; 缴费时…

基于Python+Django+MySQL+HTML的创新创业平台

DjangoMySQLHTML 基于PythonDjangoMySQLHTML的创新创业平台 用户管理 系统监控 角色管理 资源管理 参数设置 角色管理 简介 学生创新创业平台是一个功能丰富的在线教育或协作系统&#xff0c;支持中文语言环境。它提供用户管理、系统监控、多角色权限控制、资源管理、参…

手写方法实现字符串例如:“123“与整型例如:123相互转化(面试必会)

目录 二、字符串类型转化为整型 1. 初始化变量 2.定义字符串索引值 3.思考如何将字符1转化为数字1 4. 转化思路 5.考虑字符串转化负数例&#xff1a;-123456 6.完整代码 四、最后 一、前言 在c语言和c中&#xff0c;有许许多多的数据类型相互转化的方法&#xff0c;这里…

算法篇-排序

快排 算法思想&#xff1a;每次找一个基数&#xff0c;然后对数组左右遍历&#xff0c;将小于基数的数据放到左边&#xff0c;大于基数的数放到右边&#xff0c;然后将基数左边&#xff0c;右边进行迭代再排序。 public static void quickSort(int[] nums, int left, int ri…

openeuler一个服务异常占用cpu的排查过程

1 环境 硬件环境&#xff1a;LS1046A arm64 系统环境&#xff1a;openEuler release 22.03 (LTS-SP1) Linux kernel 4.19.26 2 问题说明 我的硬件平台需要适配一下 openEuler release 22.03 (LTS-SP1) 但是目前只能使用原来硬件平台的内核&#xff0c;在适配的过程中…

phar反序列化及绕过

目录 一、什么是phar phar://伪协议格式&#xff1a; 二、phar结构 1.stub phar&#xff1a;文件标识。 格式为 xxx; *2、manifest&#xff1a;压缩文件属性等信息&#xff0c;以序列化存 3、contents&#xff1a;压缩文件的内容。 4、signature&#xff1a;签名&#…

开放式耳机哪个品牌质量比较好?五大公认性能之王推荐!

作为一名热爱音乐的DJ爱好者&#xff0c;我当然知道一款适合DJ使用的开放式耳机应该具备哪些特点。最近&#xff0c;我深入评测了几款热门开放式耳机&#xff0c;从音质、舒适度、耐用性到混音功能等方面进行了全面评估。今天&#xff0c;我想为大家分享我的评测结果&#xff0…

【jdk】jdk11 jdk17 jdk21的新特性

前言&#xff1a;按照博主的个人理解&#xff0c;一般来说 除了jdk8时代 说jdk8的新特性是特指jdk8这一个版本的特性&#xff0c;之后例如jdk11 jdk17新特性 都是泛特性 什么意思呢&#xff1f; 比如jdk11新特性&#xff0c;一般是指jdk9——jdk11 这一个泛版本的所有新特性&am…

机器学习第四十四周周报 SAMformer

文章目录 week44 SAMformer摘要Abstract1. 题目2. Abstract3. 网络架构3.1 问题提出3.2 微型示例3.3 SAMformer 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程 5. 结论6.代码复现小结参考文献 week44 SAMformer 摘要 本周阅读了题为SAMformer: Unlocking the Potential…

智谱AI GLM-4V-9B视觉大模型环境搭建推理

引子 最近在关注多模态大模型&#xff0c;之前4月份的时候关注过CogVLM&#xff08;CogVLM/CogAgent环境搭建&推理测试-CSDN博客&#xff09;。模型整体表现还不错&#xff0c;不过不支持中文。智谱AI刚刚开源了GLM-4大模型&#xff0c;套餐里面包含了GLM-4V-9B大模型&…

HTTP 状态码详解及使用场景

目录 1xx 信息性状态码2xx 成功状态码3xx 重定向状态码4xx 客户端错误状态码5xx 服务器错误状态码 HTTP思维导图连接&#xff1a;https://note.youdao.com/s/A7QHimm0 1xx 信息性状态码 100 Continue&#xff1a;表示客户端应继续发送请求的其余部分。 使用场景&#xff1a;客…

昇思25天学习打卡营第3天|数据集Dataset

一、简介&#xff1a; 数据是深度学习的基础&#xff0c;高质量的数据输入将在整个深度神经网络中起到积极作用。有一种说法是模型最终训练的结果&#xff0c;10%受到算法影响&#xff0c;剩下的90%都是由训练的数据质量决定。&#xff08;doge&#xff09; MindSpore提供基于…

公司怎么管理文档外发泄密?强化企业文档安全用迅软加密软件就行了!

一、文档加密软件原理 迅软DSE加密软件对各类需要加密的文件&#xff08;如&#xff1a;技术资料、商业数据、红头文件、会议纪要、机要文件、图纸、财务报表等&#xff09;进行加密。 使用加密算法对文件自动加密&#xff0c;只有拥有正确的解密密钥或密码的人才能打开文件&…

【uni-app学习手札】

uni-app&#xff08;vue3&#xff09;编写微信小程序 编写uni-app不必拘泥于HBuilder-X编辑器&#xff0c;可用vscode进行编写&#xff0c;在《微信开发者工具》中进行热加载预览&#xff0c; 主要记录使用uni-app过程中自我备忘一些api跟语法&#xff0c;方便以后编写查找使用…

OrangePi连接Wi-Fi步骤

下面介绍的是用终端命令行的方式配置WIFI&#xff1a; 首先输入以下命令用于扫描并查看周围的WiFi热点。也可以直接连接。 nmcli dev wifi之后会在终端打出周围所有可以连接的WiFi&#xff0c;按方向键上下可以查看显示更多&#xff0c;按q键退出。 然后同样使用nmcli命令连接…

如何修改外接移动硬盘的区号

- 问题介绍 当电脑自身内存不够使用的时候&#xff0c;使用外接硬盘扩展内存是一个不错的选择。但是当使用的外接硬盘数量过多的时候&#xff0c;会出现分配硬盘的区号变动的情况&#xff0c;这种情况下会极大的影响使用的体验情况。可以通过以下步骤手动调整恢复 - 配置 版本…