当前位置: 首页 > news >正文

子进程继承父进程文件描述符导致父进程打开设备文件失败

开发过程中有时会遇到需要在程序中执行三方程序或者shell脚本,一般会通过system(), popen(), exec簇来完成该功能。我们知道以上方法会通过fork创建子进程后在子进程中执行相应指令。如图1为某个示例流程,具体的程序执行流程如图2所示,线程mypthreadFunction1首先open了一个设备文件PCMDEV,线程mypthreadFunction2中通过fork方法创建了一个子进程并通过execl执行helloword打印程序,线程mypthreadFunction1中随后会去反复开关PCMDEV设备,根据图2中右所示我们看到父线程在open设备文件PCMDEV时一直返回设备忙被占用,但是创建的子进程helloword中并未对PCMDEV设备做任何的读写开关操作.
在这里插入图片描述
图1 示例流程
在这里插入图片描述
图2 执行流程
父进程打开设备文件PCMDEV时返回设备被占用时,我们使用lsof命令确认此时占用PCMDEV设备的进程,如图3所示,PCMDEV设备居然正是被我们fork创建的子进程和helloword进程占用才导致父进程open设备文件PCMDEV一直失败。
在这里插入图片描述
图3 占用PCMDEV设备的进程

参考fork函数的用户手册,fork在创建子进程时会继承父进程打开的文件描述符,system(), popen()也会存在相同的动作。
The child inherits copies of the parent’s set of open file descriptors. Each file descriptor in the child refers to the same open file description (see open(2)) as the corresponding file descriptor in the parent. This means that the two file descriptors share open file status flags, file offset, and signal-driven I/O attributes (see the description of F_SETOWN and F_SETSIG in fcntl(2)).

为了让创建的子进程释放掉从父进程中继承的文件描述符,可以在fork之后execl之间使用如下代码主动关闭子进程下的文件描述符,

static void release_fileDesp(void)
{pid_t pid = getpid();char fileDespPath[128] = { 0 };DIR *fdDir = NULL;int ret = -1;int fd = 0;struct dirent *entry = NULL;snprintf((char *)fileDespPath, sizeof(fileDespPath) - 1, "/proc/%d/fd", pid);fdDir = opendir((const char *)fileDespPath);if (NULL == fdDir){return;}while (1){entry = readdir(fdDir);if (NULL == entry){break;}if ((0 == (strcmp(entry->d_name, "."))) || (0 == strcmp(entry->d_name, ".."))){continue;}fd = atoi(entry->d_name);if ((0 == fd) || (1 == fd) || (2 == fd))  // 标准输入,标准输出,标准错误{continue;}ret = close(fd);if (ret != 0){break;}}closedir(fdDir);return;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C#字符串基本操作
  • 【ARM】SMMU系统虚拟化整理
  • Docker容器化技术(1)
  • python中的re模块--正则表达式
  • 美图WHEE AI:包括文生图、图生图、风格模型训练多种模式图片创作绘画创作平台
  • 查看仓库文件的改变(git-status , git-diff)
  • 前后端数据交互设计到的跨域问题
  • 水利行业的智慧转型之路:分析智慧水利的核心要素与优势,展望其在提升水资源利用效率、保障水安全方面的广阔前景
  • SpringMVC注解全解析:构建高效Web应用的终极指南 (下)
  • jmeter做接口压力测试_jmeter接口性能测试
  • Qt5离线安装包无法下载问题解决办法
  • zookeeper+kafka消息队列集群部署
  • 使用 ABBYY FineReader PDF 15 在创建或转换 PDF 时自动生成书签
  • 【linux】服务器重装系统之系统盘写入准备
  • 爬虫案例(读书网)(下)
  • 《Java编程思想》读书笔记-对象导论
  • 30天自制操作系统-2
  • CentOS 7 防火墙操作
  • css系列之关于字体的事
  • Idea+maven+scala构建包并在spark on yarn 运行
  • iOS 系统授权开发
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • learning koa2.x
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • orm2 中文文档 3.1 模型属性
  • PHP 7 修改了什么呢 -- 2
  • Redis 中的布隆过滤器
  • Spring框架之我见(三)——IOC、AOP
  • vue-cli3搭建项目
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 彻底搞懂浏览器Event-loop
  • 从输入URL到页面加载发生了什么
  • 批量截取pdf文件
  • 我与Jetbrains的这些年
  • 想写好前端,先练好内功
  • 优化 Vue 项目编译文件大小
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • !!Dom4j 学习笔记
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # 达梦数据库知识点
  • # 服务治理中间件详解:Spring Cloud与Dubbo
  • # 职场生活之道:善于团结
  • #Datawhale AI夏令营第4期#多模态大模型复盘
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (2022 CVPR) Unbiased Teacher v2
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (备份) esp32 GPIO
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (一)插入排序
  • (原)本想说脏话,奈何已放下
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**