【项目 进程6】 2.13 匿名管道通信案例 2.14管道的读写特点和管道设置为非阻塞

news2024/11/23 13:19:50

文章目录

    • 2.13 匿名管道通信案例
      • 匿名管道的使用
      • 实现 ps aux | grep xxx 父子进程间通信
    • 2.14管道的读写特点和管道设置为非阻塞
      • 管道的读写特点:
      • 总结
      • 设置管道非阻塞


2.13 匿名管道通信案例

匿名管道的使用

在这里插入图片描述
在这里插入图片描述
一般匿名管道不推荐父进程与子进程交叉读写数据,一般父进程写数据子进程读数据或子进程写数据父进程读数据。

实现 ps aux | grep xxx 父子进程间通信

/*
    实现 ps aux | grep xxx 父子进程间通信
    
    子进程: 执行ps aux查看进程, 子进程结束后,将数据发送给父进程
    父进程:获取到数据,过滤
    pipe()
    execlp():执行ps aux,默认将数据发送到当前终端
    子进程将标准输出 stdout_fileno 重定向到管道的写端。  dup2函数实现文件描述符的重定向
*/

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

int main() {

    // 重点:先创建一个管道
    int fd[2];//传出参数
    int ret = pipe(fd);

    if(ret == -1) {
        perror("pipe");
        exit(0);
    }

    // 创建子进程
    pid_t pid = fork();

    if(pid > 0) {
        // 父进程
        // 关闭写端
        close(fd[1]);
        // 从管道中读取
        char buf[1024] = {0};

        int len = -1;
        //循环读:ps aux的内容相当多
        while((len = read(fd[0], buf, sizeof(buf) - 1)) > 0) {//减一原因:有字符串的结束符
            // 过滤数据输出
            printf("%s", buf);
            memset(buf, 0, 1024);//清空数组内容
        }

        //回收子进程的内容
        wait(NULL);

    } else if(pid == 0) {
        // 子进程
        // 关闭读端
        close(fd[0]);

        // 文件描述符的重定向 stdout_fileno -> fd[1]
        dup2(fd[1], STDOUT_FILENO);
        // 执行 ps aux
        execlp("ps", "ps", "aux", NULL);
        perror("execlp");
        exit(0);
    } else {
        perror("fork");
        exit(0);
    }


    return 0;
}

2.14管道的读写特点和管道设置为非阻塞

管道的读写特点:

使用管道时,需要注意以下几种特殊的情况(假设都是阻塞I/O操作)
1.所有的指向管道写端的文件描述符都关闭了(管道写端引用计数为0),有进程从管道的读端读数据,那么管道中剩余的数据被读取以后,再次read会返回0,就像读到文件末尾一样。(read读到数据返回读到数据的字节数,read读取数据失败错误返回-1)

2.如果有指向管道写端的文件描述符没有关闭(管道的写端引用计数大于0),而持有管道写端的进程也没有往管道中写数据,这个时候有进程从管道中读取数据,那么管道中剩余的数据被读取后,再次read会阻塞,直到管道中有数据可以读了才读取数据并返回。

3.如果所有指向管道读端的文件描述符都关闭了(管道的读端引用计数为0),这个时候有进程向管道中写数据,那么该进程会收到一个信号SIGPIPE(管道破裂), 通常会导致进程异常终止。

4.如果有指向管道读端的文件描述符没有关闭(管道的读端引用计数大于0),而持有管道读端的进程也没有从管道中读数据,这时有进程向管道中写数据,那么在管道被写满的时候再次write会阻塞,直到管道中有空位置才能再次写入数据并返回。

总结

读管道:
    管道中有数据,read返回实际读到的字节数。
    管道中无数据:
        写端被全部关闭,read返回0(相当于读到文件的末尾)
        写端没有完全关闭,read阻塞等待,如果设置成非阻塞,read返回值为-1

写管道:
    管道读端全部被关闭,进程异常终止(进程收到SIGPIPE信号)
    管道读端没有全部关闭:
        管道已满,write阻塞
        管道没有满,write将数据写入,并返回实际写入的字节数

设置管道非阻塞

  • nt flags = fcntl(fd[0], F_GETFL); // 获取原来的flag
  • flags |= O_NONBLOCK; // 修改flag的值
  • fcntl(fd[0], F_SETFL, flags); // 设置新的flag
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
/*
    设置管道非阻塞
    int flags = fcntl(fd[0], F_GETFL);  // 获取原来的flag
    flags |= O_NONBLOCK;            // 修改flag的值
    fcntl(fd[0], F_SETFL, flags);   // 设置新的flag
*/
int main() {

    // 在fork之前创建管道
    int pipefd[2];
    int ret = pipe(pipefd);
    if(ret == -1) {
        perror("pipe");
        exit(0);
    }

    // 创建子进程
    pid_t pid = fork();
    if(pid > 0) {
        // 父进程
        printf("i am parent process, pid : %d\n", getpid());

        // 关闭写端
        close(pipefd[1]);
        
        // 从管道的读取端读取数据
        char buf[1024] = {0};

        int flags = fcntl(pipefd[0], F_GETFL);  // 获取原来的flag
        flags |= O_NONBLOCK;            // 修改flag的值
        fcntl(pipefd[0], F_SETFL, flags);   // 设置新的flag

        while(1) {
            int len = read(pipefd[0], buf, sizeof(buf));
            printf("len : %d\n", len);
            printf("parent recv : %s, pid : %d\n", buf, getpid());
            memset(buf, 0, 1024);
            sleep(1);
        }

    } else if(pid == 0){
        // 子进程
        printf("i am child process, pid : %d\n", getpid());
        // 关闭读端
        close(pipefd[0]);
        char buf[1024] = {0};
        while(1) {
            // 向管道中写入数据
            char * str = "hello,i am child";
            write(pipefd[1], str, strlen(str));
            sleep(5);
        }
        
    }
    return 0;
}

tips:
VScode有关注释的快捷键
//注释:CTRL+K+C
取消//注释:CTRL+K+U
多行注释:ALT+SHITF+A
取消多行注释:ALT+SHITF+A

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nginx 配置 wss加密访问 mqtt

1. 在服务器上部署mqtt服务 2.在宝塔上配置域名证书 3.nginx配置websocket server {listen 80;listen 443 ssl http2;server_name ws-xx.example.com;index index.php index.html index.htm default.php default.htm default.html;root /www/wwwroot/ws-xx.example.com;loca…

金融软件技术:创新与安全并行驶

随着科技的迅速发展&#xff0c;金融行业正经历着一场前所未有的数字化转型。金融机构需要不断创新和提升效率&#xff0c;以满足客户需求&#xff0c;并保持竞争优势。在这个数字时代中&#xff0c;金融软件技术成为了实现这一目标的关键要素。本文将从两个方面探讨金融软件技…

fastadmin采坑之富文本编辑器

整了好久才弄好&#xff0c;后缀为content&#xff0c;类型为text 或者longtext类型&#xff0c;这样做命令行才能成功

Python教程(5)——Python的第一个程序

python的环境以及IDE都准备好之后&#xff0c;我们就可以开始Python之旅了。Python的第一个程序通常是打印输出"Hello, World!"&#xff0c;非常简单。以下是一个示例&#xff1a; print("Hello, World!")运行python代码 首先必须明白python是一门动态语…

Asp.net Core配置CORS 跨域无效(记录一下)

问题 学习老杨的英语网站项目&#xff0c;运行项目时&#xff0c;发现出现了跨域的问题。 然后自己建一项目&#xff0c;进行配置&#xff0c;测试&#xff0c;发现配置CORS 跨域时&#xff0c;发现跨域的配置无效&#xff0c;依旧报错。 解决 网上找了一天&#xff0c;然后…

【Uniapp,Vue】阻止父元素事件覆盖子元素事件

有个需求&#xff0c;点击一个元素&#xff0c;让弹出框显示&#xff0c;点击弹出框以外的区域&#xff0c;就关闭弹出框&#xff0c;如下代码所示。 但是这样有个问题&#xff0c;就是当弹出框显示以后&#xff0c;点击弹出框的区域也会触发父元素的点击事件&#xff0c;使得i…

【多模态】17、CORA | 将 CLIP 使用到开集目标检测

文章目录 一、背景二、方法2.1 总体结构2.2 region prompting2.3 anchor pre-matching 三、效果 论文&#xff1a;CORA: Adapting CLIP for Open-Vocabulary Detection with Region Prompting and Anchor Pre-Matching 代码&#xff1a;https://github.com/tgxs002/CORA 出处…

小程序路由跳转页面重复问题

目标&#xff1a;想要某个页面在历史中&#xff08;页面栈&#xff09;只显示一次 什么是页面栈&#xff1a; 在小程序开发中&#xff0c;页面栈是指小程序当前打开的页面的层级关系堆栈。每当打开一个新页面时&#xff0c;它会被放置在页面栈的顶部&#xff0c;而当前页面就位…

如何实现外网远程访问路由内部服务器主机端口应用?

路由器是上网常见的设备。在我们开通网络接入带宽时&#xff0c;或需要进行管理路由网络操作时&#xff0c;就需要登录路由后台设置配置相关操作。 我们在涉及路由管理方面经常会遇到一些常见的问题。路由管理入口地址是什么&#xff1f;如何配置路由有线网络或无线网络或分配…

uniapp开启消息通知/提示(使用uniPush)

亲爱的小伙伴们&#xff0c;最近对uniPush有稍许研究&#xff0c;当前研究出一些心得&#xff0c;现在分项给大家&#xff0c;希望对大家的uniapp之路有所帮助。本次的教程是教会你如何使用uniPush自定义消息通知&#xff0c;同时还附带添加消息提示音添加&#xff0c;多的不说…

linux - ping -I 的一种异常场景处理分析

实验 用ping -I 指定一个没有配置ip地址且已经up起来的网卡。 结果 linux会根据路由规则选择一个其他网卡的ip&#xff0c;但&#xff0c;还是会从该指定网卡发送。 iputils 用-I指定网卡对应的bind操作 获取该socket的本地ip&#xff0c;当bind了NIC&#xff0c;且该NIC没有…

网络传输媒体

物理层下面的传输媒体分为两种&#xff1a;导向型传输媒体和非导向型传输媒体。 一、导向型传输媒体 同轴电缆&#xff1a; 图示&#xff1a; 分类&#xff1a; 基带同轴电缆&#xff1a;用于数字传输&#xff0c;在早期局域网中广泛使用宽带同轴电缆&#xff1a;用于模拟传输…

element+vue 之预览pdf组件

1.组件previewPdf <template><el-drawer:title"drawerName":visible.sync"drawerVal":direction"direction":append-to-body"true"size"100%":before-close"drawerClose"><iframe :src"url&…

前端工程化第二章:webpack5基础(中)

文章目录 1. 处理css资源&#xff08;css文件拆分 mini-css-extract-plugin&#xff09;1.1. package.json1.2. webpack.config.js 2. 处理预编译器&#xff08;less/scss&#xff09;2.1. src/index.js2.2. src/index.less2.3. src/index.scss2.4. webpack.config.js 3. 适配&…

【《机器学习和深度学习:原理、算法、实战(使用Python和TensorFlow)》——以机器学习理论为基础并包含其在工业界的实践的一本书】

机器学习和深度学习已经成为从业人员在人工智能时代必备的技术&#xff0c;被广泛应用于图像识别、自然语言理解、推荐系统、语音识别等多个领域&#xff0c;并取得了丰硕的成果。目前&#xff0c;很多高校的人工智能、软件工程、计算机应用等专业均已开设了机器学习和深度学习…

LeetCode55.Jump-Game<跳跃游戏>

题目&#xff1a; 思路&#xff1a; 大神的思路,我是不会... 代码是&#xff1a; //大神的代码code class Solution { public:bool canJump(vector<int>& nums) {int k 0;for (int i 0; i < nums.size(); i) {if (i > k) return false;k max(k, i nums[i…

Mysql群集MHA高可用配置

目录 一、MHA概述 1.简介 2.MHA 的组成 &#xff08;1&#xff09;MHA Node&#xff08;数据节点&#xff09; &#xff08;2&#xff09;MHA Manager&#xff08;管理节点&#xff09; 3.MHA的特点 二、搭建MHA高可用数据库群集 1.主从复制 &#xff08;1&#xff09;…

整车总线系列——FlexRay 六

整车总线系列——FlexRay 六 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 没有人关注你。也无需有人关注你。你必须承认自己的价值&#xff0c;你不能…

iOS--weak的底层

怎么说 在iOS开发过程中&#xff0c;会经常使用到一个修饰词weak&#xff0c;使用场景大家都比较清晰&#xff0c;避免出现对象之间的强强引用而造成对象不能被正常释放最终导致内存泄露的问题。weak 关键字的作用是弱引用&#xff0c;所引用对象的计数器不会加1&#xff0c;并…

【自启动配置】Ubuntu 设置开机自启动脚本

Ubuntu 开机运行的脚本和当前操作系统运行的级别有关&#xff0c;OS 的运行级别大概分为七个 目录 1、查看 OS 运行级别 2、创建自启动脚本 3、添加软链接 1、查看 OS 运行级别 输入命令 runlevel 查看当前系统运行级别。当前系统的运行级别为 5 2、创建自启动脚本 在 /et…