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

news2024/11/15 8:38:47

开发过程中有时会遇到需要在程序中执行三方程序或者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;
}

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

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

相关文章

Android ListView

ListView ListView是以列表的形式展示具体内容的控件,ListView能够根据数据的长度自适应显示,如手机通讯录、短消息列表等都可以使用ListView实现。如图1所示是两个ListView,上半部分是数组形式的ListView,下半部分是简单列表Lis…

WPF学习(5) -- WPF绑定

一、双向绑定 1.代码示例 <Window x:Class"学习.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expres…

批量导出word,并导出一个zip文件

系统导出功能&#xff0c;多条数据分别导出word&#xff0c;多个word打包到一个zip进行导出&#xff0c;直接拷贝过去可用&#xff0c;如果缺包自行查找。 参考&#xff1a; Java使用word模板导出word_java根据模板导出word-CSDN博客. Action(value "exportToWordZip&qu…

高阶数据结构——并查集

1. 并查集的介绍 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合的合并及查询问题&#xff08;即所谓的并、查&#xff09;。 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#…

springboot+vue 开发记录(九)后端打包部署运行

本篇文章主要内容是后端项目写好了&#xff0c;怎么打包部署到服务器上运行。 文章目录 1. 在服务器上安装Docker2. 在Docker中装MySQL3. 在Docker中设置网桥&#xff0c;实现容器间的网络通信4. 修改后端配置文件5. 修改pom.xml文件6. 打包7. 编写DockerFile文件8. 上传文件到…

STFT:解决音频-视频零样本学习 (ZSL) 中的挑战

传统的监督学习方法需要大量的标记训练实例来进行训练,视听零样本学习的任务是利用音频和视频模态对对象或场景进行分类&#xff0c;即使在没有可用标记数据的情况下。为了解决传统监督方法的限制&#xff0c;提出了广义零样本学习&#xff08;Generalized Zero-Shot Learning,…

暴雨让服务器不怕热҈热҈热҈热҈

在AI算力呈几何倍数增长的趋势下&#xff0c;算力逐渐朝着“高性能、高密度、高耗能“发展。在高耗能的算力下&#xff0c;AI服务器功率已逐步逼近风冷散热极限&#xff0c;而液冷作为更加高效、低能耗的制冷技术&#xff0c;逐渐成为了高密度算力散热场景的首选方案。 液冷的…

Spring源码中的模板方法模式

1. 什么是模板方法模式 模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为设计模式&#xff0c;它在操作中定义算法的框架&#xff0c;将一些步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。 模板方法模式的定义&…

Linux内核编译安装 - Deepin,Debian系

为什么要自己编译内核 优点 定制化&#xff1a;你可以根据自己的硬件和需求配置内核&#xff0c;去掉不必要的模块&#xff0c;优化性能。性能优化&#xff1a;移除不需要的驱动程序和特性&#xff0c;减小内核体积&#xff0c;提高系统性能。最新特性和修复&#xff1a;获取…

网络(二)——套接字编程

文章目录 理解源IP地址和目的IP地址认识端口号认识TCP/UDP协议网络字节序socket编程接口socket 常见APIsockaddr结构 理解源IP地址和目的IP地址 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址&#xff1b; 源IP即发送方的地址&#xff0c;目的IP即接受方的…

[译] Rust标准库有些特殊,让我们改它

本篇是对 RustConf 2023中的The standard library is special. Let’s change that.这一视频的翻译与整理, 过程中为符合中文惯用表达有适当删改, 版权归原作者所有. 今天我将讨论Rust的标准库,更具体地说,是关于标准库有何特殊之处,以及为什么我们应该改变这一点。首先声明一下…

探索 Prompt 的世界:让你的 AI 更智能

探索 Prompt 的世界&#xff1a;让你的 AI 更智能 引言什么是 Prompt&#xff1f;Prompt 的重要性如何编写有效的 Prompt1. 清晰明确2. 包含关键细节3. 提供上下文 实践中的 Prompt 技巧1. 多次迭代2. 实验不同风格3. 结合实际应用 总结 引言 随着人工智能&#xff08;AI&…

通过vm可以访问那些属性——06

1.通过vue实例都可以访问那些属性&#xff1f;&#xff08;通过vm都可以vm.什么&#xff09; vue实例中的属性很多。有的以$开始&#xff0c;有的以_开始。 所有以$开始的属性&#xff0c;可以看做是公开的属性&#xff0c;这些属性是提供给程序员使用的 所有以_开始的属性&…

PyTorch是使用GPU和CPU优化的深度学习张量库——torchvision

torchvision datasets torchvision.datasets 包含了许多标准数据集的加载器。例如&#xff0c;CIFAR10 和 ImageFolder 是其中两个非常常用的类。 CIFAR10 CIFAR10 数据集是一个广泛使用的数据集&#xff0c;包含10类彩色图像&#xff0c;每类有6000张图像&#xff08;5000张…

<数据集>夜间车辆识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;5000张 标注数量(xml文件个数)&#xff1a;5000 标注数量(txt文件个数)&#xff1a;5000 标注类别数&#xff1a;8 标注类别名称&#xff1a;[car, pedestrian, traffic light, traffic sign, bicycle, bus, truck…

Leetcode(经典题)day2

H指数 274. H 指数 - 力扣&#xff08;LeetCode&#xff09; 先对数组排序&#xff0c;然后从大的一头开始遍历&#xff0c;只要数组当前的数比现在的h指数大就给h指数1&#xff0c;直到数组当前的数比现在的h指数小的时候结束&#xff0c;这时h的值就是要返回的结果。 排序…

Ubuntu搭建Android架构so库交叉编译环境

目录 前言一、下载NDK并安装二、安装NDK三、配置交叉编译工具链四、编写交叉编译脚本 前言 需要将一些源码编译成Android可用的架构的so库 一、下载NDK并安装 https://developer.android.google.cn/ndk/downloads/ 二、安装NDK 将下载下来的android-ndk-r23b-linux.zip解压…

17099 周工作计划安排

这个问题可以通过动态规划来解决。我们可以定义一个数组d&#xff0c;其中d[i]表示第i周选择项目后&#xff0c;产生的最大效益和。然后我们可以通过比较选择低压项目和高压项目的效益&#xff0c;来更新d[i]。 以下是解题步骤&#xff1a; 1. 初始化数组&#xff1a;首先&am…

《Linux系统编程篇》认识在linux上的文件 ——基础篇

前言 Linux系统编程的文件操作如同掌握了一把魔法钥匙&#xff0c;打开了无尽可能性的大门。在这个世界中&#xff0c;你需要了解文件描述符、文件权限、文件路径等基础知识&#xff0c;就像探险家需要了解地图和指南针一样。而了解这些基础知识&#xff0c;就像学会了魔法咒语…

视频播放器的问题

<template><div class"app-container"><el-form :model"queryParam" ref"queryForm" :inline"true"><el-form-item label"题目ID&#xff1a;"><el-input v-model"queryParam.id" cle…