linux驱动资源没有及时释放排查

linux驱动资源没有及时释放排查

之前项目过程有遇到一个问题,明明应用已经close fd了,但是再次open设备的时候会出现“device is busy”的情况。刚开始出现这个问题的时候,还以为是应用没有及时的close fd导致的异常,同时排查了内核close设备的流程,close流程如下:

// fs/open.c
SYSCALL_DEFINE1(close, unsigned int, fd)close_fd(fd)filp_close(file, files)filp->f_op->flush(filp, id)fput(filp);fput_many(file, 1)

通过上面,并没有发现有相关的 file->f_op->release(inode, file) 行为,那么这个驱动的释放,到底是在哪里进行的呢?我们再关注一下 fput_many() 函数的实现。

static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);void fput_many(struct file *file, unsigned int refs)
{// 对file句柄的计数-1并测试是否为0,返回true则是可释放if (atomic_long_sub_and_test(refs, &file->f_count)) {struct task_struct *task = current;if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) {init_task_work(&file->f_u.fu_rcuhead, ____fput);if (!task_work_add(task, &file->f_u.fu_rcuhead, TWA_RESUME))return;/** After this task has run exit_task_work(),* task_work_add() will fail.  Fall through to delayed* fput to avoid leaking *file.*/}if (llist_add(&file->f_u.fu_llist, &delayed_fput_list))schedule_delayed_work(&delayed_fput_work, 1); // 最后这里调度delayed_fput_work,也就是调用delayed_fput()}
}void fput(struct file *file)
{fput_many(file, 1);
}

在 delayed_fput() 函数中,最后调用到 __fput() 函数。

/* the real guts of fput() - releasing the last reference to file*/
static void __fput(struct file *file)
{struct dentry *dentry = file->f_path.dentry;struct vfsmount *mnt = file->f_path.mnt;struct inode *inode = file->f_inode;fmode_t mode = file->f_mode;if (unlikely(!(file->f_mode & FMODE_OPENED)))goto out;might_sleep();fsnotify_close(file);/** The function eventpoll_release() should be the first called* in the file cleanup chain.*/eventpoll_release(file);locks_remove_file(file);ima_file_free(file);if (unlikely(file->f_flags & FASYNC)) {if (file->f_op->fasync)file->f_op->fasync(-1, file, 0);}if (file->f_op->release)file->f_op->release(inode, file); //真正在,在这里才会进行驱动的释放if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL &&!(mode & FMODE_PATH))) {cdev_put(inode->i_cdev);}fops_put(file->f_op);put_pid(file->f_owner.pid);put_file_access(file);dput(dentry);if (unlikely(mode & FMODE_NEED_UNMOUNT))dissolve_on_fput(mnt);mntput(mnt);
out:file_free(file);
}

那么,回头我们的问题,为什么应用调用了close函数,驱动却没有释放呢?从上面的代码流程来看,只有一个可能,那就是这个file的引用计数不为0,还有其他地方在引用,导致无法release。

在内核搜索代码可以发现,调用 get_file() 函数,将会导致这个引用计数f_count自增。

最后分析代码发现,在open的时候, 没有用O_CLOEXEC flag,导致进程中如果出现popen或者system打开的进程将会拷贝一份当前进程的fd信息,导致资源引用计数+1,需要等待所有进程都退出后,fd的引用计数才为0。

所以针对这个问题,只需要在open节点的时候,增加O_CLOEXEC这个标识即可。

下面附上O_CLOEXEC 这个标识的作用说明:

   O_CLOEXEC (since Linux 2.6.23)Enable the close-on-exec flag for the new file descriptor.  Specifying this flag permits a program to avoid additional fcntl(2) F_SETFD operations to set the FD_CLOEXEC flag.Note that the use of this flag is essential in some multithreaded programs, because using a separate fcntl(2) F_SETFD operation to set the FD_CLOEXEC flag does not suffice to avoid race conditions where one threadopens a file descriptor and attempts to set its close-on-exec flag using fcntl(2) at the same time as another thread does a fork(2) plus execve(2).  Depending on the order of execution, the race may  lead  to  thefile descriptor returned by open() being unintentionally leaked to the program executed by the child process created by fork(2).  (This kind of race is in principle possible for any system call that creates a filedescriptor whose close-on-exec flag should be set, and various other Linux system calls provide an equivalent of the O_CLOEXEC flag to deal with this problem.)

这个标识,在多线程的程序中是必不可少的,避免open返回的文件描述符无意泄漏给fork创建的子进程。

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

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

相关文章

Java的JDBC与Druid数据连接池笔记

第一章 JDBC 1.1 JDBC简介 1.1.1 JDBC概念 JDBC就是使用Java语言操作关系型数据库的一套API 全称(Java DataBase Connectivity)Java数据库连接 1.1.2 JDBC本质 官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口 各个数据库厂商去实现这套接口,提供数据库…

使用 jQuery 选择器获取页面元素,然后利用 jQuery 对象的 css() 方法设置其 display 样式属性,从而实现显示和隐藏效果。

在页面中显示电影排行榜 当单击“(收起)”链接时,排行榜中后三项的电影名称隐藏而且链接的文本更改为“(展开) ” 当单击“(展开)”的链接时,后三项的电影名称重新显示且链接的文本…

视频剪辑技巧大揭秘:轻松掌握为视频添加梦幻光晕效果的绝妙方法!

在这个视觉盛宴的时代,每一个画面都渴望被赋予独特的魅力与魔法。今天,我要为你揭秘一个神秘的视频剪辑技巧——给视频添加光晕效果,让你的作品瞬间脱颖而出,成为朋友圈的焦点 首先,你可以打开原视频进行查看。此时&am…

QT自定义标题栏窗口其一:实现拖动及可拉伸效果

1、效果 2、核心代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(paren

【字节序】

1. 字节序(Endianness)问题 不同计算机体系结构可能采用不同的字节序来存储多字节数据。字节序有两种主要形式: 大端序(Big-endian):高位字节存储在低地址。 小端序(Little-endian&#xff09…

高速公路声光预警定向广播助力安全出行

近年来,高速重大交通事故屡见不鲜,安全管控一直是高速运营的重中之重。如何利用现代化技术和信息化手段,创新、智能、高效的压降交通事故的发生概率,优化交通安全管控质量,是近年来交管部门的主要工作,也是…

unity UGUI画线(Image方式)

/// <summary>/// 画线/// 注意&#xff1a;startPoint和endPoint&#xff0c;须和lineTransform在同一路径层级下的位置关系&#xff01;&#xff01;&#xff01;/// </summary>/// <param name"self"></param>/// <param name"li…

Asp.net core Authoriation Middleware实现权限控制的例子

ASP.NET Core Authorization Middleware 是 ASP.NET Core 框架中用于处理授权的中间件组件。它允许开发者在应用程序中实现细粒度的访问控制&#xff0c;确保只有合适的用户才能访问特定的资源或执行特定的操作。 核心概念 策略&#xff08;Policies&#xff09;&#xff1a;策…

解决不能拉取 docker 镜像

# 编辑镜像仓库文件 sudo vi /etc/docker/daemon.json { "registry-mirrors": ["https://registry.docker-cn.com","https://s3d6l2fh.mirror.aliyuncs.com"] }# 重启docker sudo systemctl restart docker参考 https://blog.csdn.net/u01019733…

timescaledb:单机基于postgresql-15安装timescaledb

配置yum sudo yum install https://download.postgresql.org/pub/repos/yum/reporpms/F-$(rpm -E %{fedora})-x86_64/pgdg-fedora-repo-latest.noarch.rpm配置yum源 sudo tee /etc/yum.repos.d/timescale_timescaledb.repo <<EOL [timescale_timescaledb] nametimescal…

将强化学习重新引入 RLHF

我们很高兴在 TRL 中介绍 RLOO (REINFORCE Leave One-Out) 训练器。作为一种替代 PPO 的方法&#xff0c;RLOO 是一种新的在线 RLHF 训练算法&#xff0c;旨在使其更易于访问和实施。特别是&#xff0c; RLOO 需要的 GPU 内存更少&#xff0c;并且达到收敛所需的挂钟时间也更短…

前端Vue实现萤石云播放视频

下载依赖 npm install ezuikit-js --save 完整代码 <template><div class"home"><div id"video-container"></div></div> </template> <script> import EZUIKit from "ezuikit-js";export default…

ICAS英格尔引领企业绿色转型之路:深度解析ISO14064温室气体核查与审定服务

在全球范围内&#xff0c;气候变化正迅速成为影响企业战略决策、运营效率及长期可持续发展的关键因素。ICAS英格尔作为全球领先的认证机构&#xff0c;致力于通过ISO14064温室气体核查与审定服务&#xff0c;帮助企业应对这一挑战&#xff0c;实现绿色转型&#xff0c;提升环境…

前端模糊搜索关键字高亮

效果 代码 <template><view class"flexStart new-box"><view class"company"><!-- 输入框样式 --><view class"spaceBetween companyName" click.stop"isCompany true"><input type"text&quo…

如果已经登录,输入白名单路由想访问白名单页面被重定向其他页面

如果用户已经登录&#xff0c;但尝试访问白名单页面时被重定向到了其他页面&#xff0c;这可能是由于路由守卫的逻辑设置不正确。以下是一些可能的原因和解决方案&#xff1a; 可能的原因&#xff1a; 路由守卫逻辑错误&#xff1a;路由守卫可能错误地将已登录用户重定向到登…

C盘满了怎么清理?一招让你远离C盘空间不足的烦恼

C盘满了怎么清理&#xff1f;一招让你远离C盘空间不足的烦恼&#xff0c;当C盘空间满了时&#xff0c;会给我们来一系列烦恼和潜在问题。比如&#xff1a;系统运行缓慢、程序崩溃或无法安装、启动时间变长、系统不稳定、文件管理困难、游戏卡顿、电脑卡顿、系统故障等问题&…

使用css实现打开抽屉效果(css过渡动画)

方法一&#xff0c;使用高度方式&#xff0c;高度从0到展示进行过渡 HTML代码&#xff1a; <div class"container"><div class"menu">菜单</div><div class"box"></div></div>CSS代码&#xff1a; .box {wi…

Linux使用Docker部署mysql5.7

一、拉取镜像 docker pull mysql:5.7 二、查看镜像 docker images 三、创建容器 这里稍微解释下 -p参数是端口映射 -v参数是数据卷挂载 数据卷挂载是Docker中的一种功能&#xff0c;它允许将主机上的目录或文件系统与容器内的目录绑定&#xff0c;实现数据的持久化存储…

代码随想录算法训练营第45天(py)| 动态规划 | 198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 力扣链接 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金。 如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组nums&#xff0c;计算你 不触动警报装置的情况下 &…

短剧片源授权,类目丰富优惠多,抢先一步更新你的短剧系统片库!

前言 如今的短剧作为一种新兴的视听艺术形式&#xff0c;正以其独特的魅力迅速占领市场高地。为了满足广大短剧爱好者和从业者的需求&#xff0c;我们提供短剧片源授权服务&#xff0c;凭借剧场独家提供的丰富片源&#xff0c;助力您轻松更新短剧系统片库&#xff0c;抢占市场…