管道读写规则及 PIPE_BUF 涉及的写原子性问题

结论:
一、当管道内没有数据可读时
O_NONBLOCK disable:read 调用阻塞,直到有可读数据
O_NONBLOCK enable: read 调用返回 -1,errno 值为 EAGAIN

二、当管道已满或者剩余空间不够时
O_NONBLOCK disable:write 调用阻塞,直到有进程读走数据,管道中有足够大的可用空间
O_NONBLOCK enable: write 调用返回 -1,errno 值为 EAGAIN

匿名管道默认是阻塞模式,可通过以下示例修改为非阻塞模式

int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);

命名管道的阻塞模式和非阻塞模式设定参见以下示例

open("fifo", flags | O_NONBLOCK);  //非阻塞
open("fifo", flags);  //阻塞

三、
如果所有管道写端对应的文件描述符被关闭,则 read 调用返回 0
如果所有管道读端对应的文件描述符被关闭,则 write 调用会产生信号 SIGPIPE,进而可能导致写进程退出

四、man 7 pipe
1、当要写入的数据量n <= PIPE_BUF 时,linux 将保证写入的原子性
O_NONBLOCK disable:如果管道中有足够大的可用空间便写入;否则 write 调用阻塞,直到管道中有足够大的可用空间
O_NONBLOCK enable: 如果管道中有足够大的可用空间便写入;否则 write 调用返回 -1,errno 值为 EAGAIN
2、当要写入的数据量n > PIPE_BUF 时,linux 将不再保证写入的原子性
O_NONBLOCK disable:write 直到将所有数据写入管道后返回,期间可能有其他进程穿插写入
O_NONBLOCK enable: 如果管道已满,write 调用返回 -1,errno 值为 EAGAIN;否则实际写入的数据量为 1 ~ n,即部分写入,期间可能有其他进程穿插写入

在这里插入图片描述

验证如下:
1、O_NONBLOCK disable:read 调用阻塞

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>int main(void)
{int    fds[2];pid_t  pid;time_t t;char   buf[10] = {0};if(0 != pipe(fds)){perror("pipe error");exit(EXIT_FAILURE);}pid = fork();if (-1 == pid){perror("fork error");exit(EXIT_FAILURE);}if (0 == pid){close(fds[0]);  //关闭读端sleep(10);write(fds[1], "hello", 5);exit(EXIT_SUCCESS);}close(fds[1]);  //关闭写端t = time(NULL);read(fds[0], buf, sizeof(buf));t = time(NULL) - t;printf("receive data: %s, interval time: %ds\n", buf, t);waitpid(pid, NULL, 0);return 0;
}
/** receive data: hello, interval time: 10s*/

2、O_NONBLOCK enable:read 调用返回 -1,errno 值为 EAGAIN(11)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>int main(void)
{int    fds[2], flags;pid_t  pid;char   buf[10] = {0};if(0 != pipe(fds)){perror("pipe error");exit(EXIT_FAILURE);}pid = fork();if (-1 == pid){perror("fork error");exit(EXIT_FAILURE);}if (0 == pid){close(fds[0]);sleep(10);write(fds[1], "hello", 5);exit(EXIT_SUCCESS);}close(fds[1]);flags = fcntl(fds[0], F_GETFL);fcntl(fds[0], F_SETFL, flags | O_NONBLOCK);if (-1 == read(fds[0], buf, sizeof(buf))){perror("read error");printf("errno: %d\n", errno);waitpid(pid, NULL, 0);exit(EXIT_FAILURE);}printf("receive data: %s\n", buf);waitpid(pid, NULL, 0);return 0;
}
/** read error: Resource temporarily unavailable* errno: 11*/

3、O_NONBLOCK disable:write 调用阻塞

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>int main(void)
{int  fds[2];char buf[4096];int  count = 0;if(0 != pipe(fds)){perror("pipe error");exit(EXIT_FAILURE);}memset(buf, 'A', sizeof(buf));while(1){count += write(fds[1], buf, sizeof(buf));printf("writed data length: %d\n", count);}return 0;
}
/*writed data length: 4096writed data length: 8192writed data length: 12288writed data length: 16384writed data length: 20480writed data length: 24576writed data length: 28672writed data length: 32768writed data length: 36864writed data length: 40960writed data length: 45056writed data length: 49152writed data length: 53248writed data length: 57344writed data length: 61440writed data length: 65536阻塞卡住*/

4、O_NONBLOCK enable: write 调用返回 -1,errno 值为 EAGAIN(11)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>int main(void)
{int  fds[2], flags;char buf[4096];int  ret, count = 0;if(0 != pipe(fds)){perror("pipe error");exit(EXIT_FAILURE);}flags = fcntl(fds[1], F_GETFL);fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);memset(buf, 'A', sizeof(buf));while(1){ret = write(fds[1], buf, sizeof(buf));if (-1 == ret){perror("write error");printf("errno: %d\n", errno);exit(EXIT_FAILURE);}count += ret;printf("writed data length: %d\n", count);}return 0;
}
/*writed data length: 4096writed data length: 8192writed data length: 12288writed data length: 16384writed data length: 20480writed data length: 24576writed data length: 28672writed data length: 32768writed data length: 36864writed data length: 40960writed data length: 45056writed data length: 49152writed data length: 53248writed data length: 57344writed data length: 61440writed data length: 65536write error: Resource temporarily unavailableerrno: 11*/

5、所有管道写端对应的文件描述符被关闭,read 调用返回 0
6、所有管道读端对应的文件描述符被关闭,write 调用会产生信号 SIGPIPE

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue时间轴

之前有这样子的需求没有用第三方插件于是自己写一个简单的时间轴 时间轴滚动条并左右切换滚动条位置相对应移动 <div class"time-scrollbar"><div v-if"timeLineData.length>0" class"scrollbar-content"><div class"ar…

vue3的基本使用(1)

Vue3的基本使用&#xff08;1&#xff09; 初识vue31. vue3简介2. 性能提升3. 源码升级 Vue3的创建1. vue-cli创建2. vite创建 Composition API的区别&#xff08;组合式&#xff09;setup函数响应式数据1. ref响应式2. reactive响应式 toRefs与toRef简单介绍 初识vue3 1. vue…

Vue系列-环境快速搭建

vue环境快速搭建 演示视频 快速搭建Vue开发环境pnpm和yarn 1. 基本信息 作者: GMCY系列: Vue仓库: GitHub | Gitee话题(GitHub): tools \ vue创建时间: 2024/03/02 2. 介绍 功能 批处理文件vue 环境的快速搭建nodejs, npm, pnpm, yarn 自动 下载安装npm, pnpm, yarn 自动 …

CVE-2024-27198 JetBrains TeamCity 身份验证绕过漏洞分析

漏洞简介 JetBrains TeamCity 是一款由 JetBrains 公司开发的持续集成和持续交付服务器。它提供了强大的功能和工具&#xff0c;旨在帮助开发团队构建、测试和部署他们的软件项目 JetBrains TeamCity发布新版本修复了两个高危漏洞JetBrains TeamCity 身份验证绕过漏洞(CVE-20…

企智汇:引领企业项目管理的数字智能化管理系统工具!

随着数字化时代的来临&#xff0c;企业对项目管理的要求也日益增高。面对日益复杂的业务流程和海量数据&#xff0c;如何有效地管理项目、整合资源、优化流程、提高管理效率&#xff0c;成为了摆在企业面前的重要课题。在这样的背景下&#xff0c;专业做了10年项目管理系统的&a…

vsphere虚拟机迁移是灰色如何解决

vsphere虚拟机迁移是灰色如何解决 问题描述&#xff1a; 在vsphere中&#xff0c;迁移虚拟机时迁移按钮是灰色&#xff0c;无法迁移&#xff0c;关机之后也无法迁移 虚拟机按钮为灰色 找到虚拟机存储对应的位置&#xff0c;查询是否有.vmx虚拟机文件 查询中发现有.vmx文件存…

JS使用方式

JS是解释性语言&#xff0c;所以不需要搭建类似C#/Java之类的开发运行环境&#xff0c;因为他们是编译型语言。JS一般运行在浏览器中或者node环境中&#xff0c;这里都是JS引擎的功劳。 node环境使用 推荐使用nvm管理node版本&#xff0c;nrm管理代理地址。 安装node&#xf…

P2241 统计方形(数据加强版) python解法

求n*m网格内矩形的数目 - tenos - 博客园 (cnblogs.com) 法一&#xff08;题解推规律暴力枚举得到&#xff09;&#xff1a; n,mmap(int,input().split()) sqr,rec0,0 #正方形和长方形个数 #以长宽做循环&#xff0c;每次求n*m大小的矩形的个数 #题解是从0开始的&#xff0c;我…

供应链管理(SCM):界面设计全面扫盲,得供应链者得天下

大家伙&#xff0c;我是大千UI工场&#xff0c;专注UI分享和项目接单&#xff0c;本期带来供应链系统的设计分享&#xff0c;欢迎大家关注、互动交流。 一、什么是SCM SCM系统是供应链管理&#xff08;Supply Chain Management&#xff09;系统的缩写。供应链管理是指协调和管…

信号处理--卷积残差网络实现单通道脑电的睡眠分期监测

目录 背景 亮点 环境配置 数据 方法 结果 代码获取 参考文献 背景 人类大约花三分之一的时间睡觉&#xff0c;这使得监视睡眠成为幸福感的组成部分。 在本文中&#xff0c;提出了用于端到端睡眠阶段的34层深残留的Convnet架构 亮点 使用深度1D CNN残差架构&#xff0…

支小蜜校园防欺凌报警系统如何识别霸凌

校园霸凌给受害者带来了深重的心理和身体伤害。为了有效应对这一问题&#xff0c;校园防欺凌报警系统应运而生&#xff0c;其核心技术在于如何准确、迅速地识别霸凌行为。那么校园防欺凌报警系统是如何识别霸凌的呢&#xff1f; 图像识别技术 这些系统利用高清摄像头捕捉校园…

【软件测试】如何申请专利?

一、专利类型 在软件测试领域&#xff0c;可以申请发明专利、实用新型专利和外观设计专利。其中&#xff0c;发明专利是最常见的专利类型&#xff0c;它保护的是软件测试方法、系统和装置等技术方案。 二、申请专利的条件 申请专利需要满足新颖性、创造性和实用性三个条件。…