源码学习:文件描述符

在进程描述学习中,扯到了max_fds,接着就联想到了日常运维中常见的ulimit参数、sysctl内核参数,原来以为max_fds与这些个关联性比较强,但经过一早上折腾以后,发现其实还是有一些差距的。但是在学习过程中,却是东拉西扯折腾出了很多其他东西。

现在尝试把这些东西都统一消化一下。

文件描述符File Descriptor

fd 是 File descriptor 的缩写,中文名叫做:文件描述符。文件描述符是一个非负整数,本质上是一个索引值。

fd是索引值!fd是索引值!fd是索引值!

重要的事情说三遍。

什么时候需要fd

当打开一个文件时,内核向进程返回一个文件描述符( open 系统调用得到 ),后续 read、write 这个文件时,则只需要用这个文件描述符来标识该文件,将其作为参数传入 read、write 。

如同task_struct内的struct files_struct     *files

struct task_struct {// .../* Open file information: */struct files_struct     *files;// ...}

此处的files 是一个指针,指向一个为 struct files_struct 的结构体。这个结构体就是用来管理该进程打开的所有文件的管理结构。

struct task_struct 是进程的抽象封装,标识一个进程。当创建一个进程,其实也就是 new 一个 struct task_struct 出来;

上面代码通过进程结构体引出了 struct files_struct 这个结构体。这个结构体管理某进程打开的所有文件的管理结构,核心代码如下:

struct files_struct {
....struct fdtable __rcu *fdt;struct fdtable fdtab;  //动态数组
....struct file __rcu * fd_array[NR_OPEN_DEFAULT]; //静态数组
....
};

files_struct 结构体是用来管理所有打开的文件的。通过数组进行管理,所有打开的文件结构都在数组里。struct files_struct内有两个数组,一个静态数组,一个动态数组。

由于大部分进程只会打开少量的文件,所以静态数组就够了,这样就不用另外分配内存。如果超过了静态数组的阈值,那么就动态扩展,使用动态数组。

静态数组

#define NR_OPEN_DEFAULT BITS_PER_LONG

这是一个静态数组,随着 files_struct 结构体分配出来的,在 64 位系统上,静态数组大小为 64;

定义代码如下,BITS_PER_LONG在64位系统上为64:

#define NR_OPEN_DEFAULT BITS_PER_LONG

动态数组

struct fdtable

这个是数组管理结构,封装用来管理 fd 的结构体,代码如下

struct fdtable {unsigned int max_fds;struct file __rcu **fd;      /* current fd array */unsigned long *close_on_exec;unsigned long *open_fds;unsigned long *full_fds_bits;struct rcu_head rcu;
};

fdtable.fd 这个字段是一个二级指针,指向 fdtable.fd 是一个指针字段,指向的内存地址还是存储指针的(元素指针类型为  struct file * )。换句话说,fdtable.fd 指向一个数组,数组元素为指针(指针类型为 struct file *)。其中 max_fds 指明数组边界。

file_struct 本质上是用来管理所有打开的文件的,内部的核心是由一个静态数组和动态数组管理结构实现。而文件描述符fd 就是这个数组的索引,也就是数组的槽位编号已。 通过非负数 fd 就能拿到对应的 struct file 结构体的地址。

日常运维与fd擦边的参数

1. file-max

/proc/sys/fs/file-max

这个文件决定了系统级别所有进程可以打开的文件描述符的数量限制,尝试分配超过file-max值的文件描述符将通过printk报告,查找包含"VFS: file-max limit reached"的信息。

root@linux-kernel:/# sysctl -a | grep -i file-max fs.file-max = 65535

修改方式

echo "fs.file-max = 65535000" >> /etc/sysctl.conf

sysctl -p

2. file-nr

这个是一个状态指示的文件,一共三个值,第一个代表全局已经分配的文件描述符数量,第二个代表自由的文件描述符(待重新分配的),第三个代表总的文件描述符的数量。

Linux 2.6 版本始终将空闲文件句柄数量报告为0 —— 这不是错误,而是表示已分配的文件句柄数量恰好等于已使用的文件句柄数量。

root@linux-kernel:/# cat /proc/sys/fs/file-nr

1248    0    9223372036854775807

3. nr_open

表示一个进程可以分配的最大文件句柄数量。默认值是1024*1024(1048576),对大多数机器来说应该足够了。实际限制取决于RLIMIT_NOFILE资源限制。

unsigned int sysctl_nr_open __read_mostly = 1024*1024;
unsigned int sysctl_nr_open_min = BITS_PER_LONG;

4. RLIMIT_NOFILE

RLIMIT_NOFILE是一个用于限制单个进程可以打开的文件描述符数量的资源限制。它定义了当前进程能够同时打开的最大文件描述符数量。这个限制是针对每个进程的,而不是系统整体的。通过调整这个限制,可以控制每个进程能够同时处理的文件数量,从而对系统的资源利用进行管理和优化。

可以通过ulimit -n 配置(重启后失效) 或者配置/etc/security/limits.conf永久生效。openEuler默认为1024

其中nofile为number of open file, 为打开文件数量,针对单个进程和用户。

# /etc/security/limits.conf //将可打开数量设置为65535 
* soft nofile 65535 
* hard nofile 65535

对应limit默认值配置源码如下,用户空间的NR_OPEN配置为1024.

另外可以通过程序接口 setrlimit()、getrlimit() 进行设置

int do_prlimit(struct task_struct *tsk, unsigned int resource,struct rlimit *new_rlim, struct rlimit *old_rlim)
{struct rlimit *rlim;int retval = 0;...if (new_rlim) {if (new_rlim->rlim_cur > new_rlim->rlim_max)return -EINVAL;if (resource == RLIMIT_NOFILE &&new_rlim->rlim_max > sysctl_nr_open)return -EPERM;}...
}

在/proc/sys/fs下三个参数的加载源码

static struct ctl_table fs_table[] = {...{.procname   = "file-nr",.data       = &files_stat,.maxlen     = sizeof(files_stat),.mode       = 0444,.proc_handler   = proc_nr_files,},{.procname   = "file-max",.data       = &files_stat.max_files,.maxlen     = sizeof(files_stat.max_files),.mode       = 0644,.proc_handler   = proc_doulongvec_minmax,.extra1     = &zero_ul,.extra2     = &long_max,},{.procname   = "nr_open",.data       = &sysctl_nr_open,.maxlen     = sizeof(unsigned int),.mode       = 0644,.proc_handler   = proc_dointvec_minmax,.extra1     = &sysctl_nr_open_min,.extra2     = &sysctl_nr_open_max,}...

nr_open、file-max与RLIMIT_NOFILE的对比

范围:

  • nr_open:单个进程的文件描述符最大值。
  • file-max:系统范围内所有进程的文件描述符总数。
  • RLIMIT_NOFILE:每个进程的文件描述符软限制和硬限制。

层级:

  • nr_open 和 RLIMIT_NOFILE 作用于进程级别,控制单个进程可以打开的文件数量。
  • file-max 作用于系统级别,控制整个系统可以打开的文件数量。

限制机制:

  • nr_open 提供了一个系统范围内的进程级硬限制。
  • RLIMIT_NOFILE 可以通过用户或管理员动态调整,灵活性较高。
  • file-max 确保系统不会超出总的文件描述符资源,避免资源枯竭。

关联性:

在 Linux 系统中,NR_OPEN 是一个内核中定义的常量,它表示整个系统可以同时打开的文件描述符的最大数量。一旦这个常量在内核中设置为某个值(比如1024),那么系统级别的文件描述符总数就会受到这个限制。

用户进程可以通过 RLIMIT_NOFILE 这个资源限制来控制其自身可以打开的文件描述符数量。这个限制是针对每个进程的,与 NR_OPEN 不同,它影响的是单个进程的能力,而不是整个系统。

如果 NR_OPEN 被设置为 1024,这意味着整个系统在任何时刻都不会超过 1024 个打开的文件描述符。但是,每个单独的进程可以通过 RLIMIT_NOFILE 设置自己的最大文件描述符数量。默认情况下,如果不显式设置,RLIMIT_NOFILE 的值通常会比较大,远超过 NR_OPEN 的设置,允许进程在其自身的限制内操作。

因此,即使 NR_OPEN 设置为 1024,用户进程仍然可以通过设置适当的 RLIMIT_NOFILE 来打开更多的文件描述符,只要它们不超过其自身的限制。这种设置允许操作系统在系统级别保持资源的控制,同时让每个进程有足够的灵活性来管理自己的资源使用。

在设置和检查文件描述符时,内核会结合这几个参数来确保资源使用在合理范围内。例如,当一个进程请求打开新的文件描述符时,内核会检查 RLIMIT_NOFILE 和 nr_open,同时在全局范围内检查是否超过 file-max。

通过这些参数的组合,Linux 内核能够灵活而有效地管理文件描述符资源,确保系统稳定和高效运行。

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

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

相关文章

SAP配置发布WebService接口并调用(超级详细)

文章目录 前言一、案例介绍/笔者需求二、WebService是什么? a.传输协议 b.数据协议 c.WSDL d.UDDI 三、WebService 和 WebApi 的区别以及优缺点 a.主要区别 b.优缺点 四、SAP如何发布一个webser…

LVGL实现字库的下载和使用

1 字库 字库的概念:相应文字或字符的合集。 点阵字库:按字库顺序排列的字符/汉字字模的合集。 LVGL中字库使用Unicode编码,Unicode 是全球文字统一编码。它把世界上的各种文字的每一个字符指定唯一编码,实现跨语种、跨平台的应…

示例:WPF中推荐一个Diagram开源流程图控件

一、目的&#xff1a;分享一个自研的开源流程图控件 二、使用方法 1、引用Nuget包&#xff1a; 2、添加节点列表和绘图控件 <DockPanel><ItemsControl DockPanel.Dock"Left"><h:GeometryNodeData Text"节点"/></ItemsControl><…

[vue2/vue3] 详细剖析watch、computed、watchEffect的区别,原理解读

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;我是前端菜鸟的自我修养&#xff01;今天给大家分享【深入剖析watch、computed、watchEffect的区别】&#xff0c;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;原创不易&#xff0c;如果能帮助到带大家…

Rust 跨平台-Android 和鸿蒙 OS

1. 安装 rustup rustup 是 Rust 的安装和版本管理工具 $ curl --proto https --tlsv1.2 https://sh.rustup.rs -sSf | sh 该命令会安装 rusup 和最新的稳定版本的 Rust&#xff1b;包括&#xff1a; rustc Rust 编译器&#xff0c;用于将 Rust 代码编译成可执行文件或库。 ca…

网络爬虫(一)

1. 深度优先爬虫&#xff1a;深度优先爬虫是一种以深度为优先的爬虫算法。它从一个起始点开始&#xff0c;先访问一个链接&#xff0c;然后再访问该链接下的链接&#xff0c;一直深入地访问直到无法再继续深入为止。然后回溯到上一个链接&#xff0c;再继续深入访问下一个未被访…

redis,memcached,nginx网络组件

课程目标&#xff1a; 1.网络模块要处理哪些事情 2.reactor是怎么处理这些事情的 3.reactor怎么封装 4.网络模块与业务逻辑的关系 5.怎么优化reactor? io函数 函数调用 都有两个作用&#xff1a;io检测 是否就绪 io操作 1. int clientfd accept(listenfd, &addr, &l…

猫头虎 2024年上半年个人总结:科技自媒体的进击与突破

猫头虎 &#x1f42f; 2024年上半年个人总结&#xff1a;科技自媒体的进击与突破 &#x1f680; 大家好&#xff0c;我是猫头虎&#xff0c;实名李彦斌&#xff0c;陕西商洛人&#xff0c;今年26岁&#xff0c;目前在北京工作&#xff0c;全栈软件工程师、科技自媒体博主、某科…

CSS基础学习记录(6)

目录 1、从最基本的页面开始 2、添加图像/浮层部分 3、位置调整 4、添加动效 4.1、添加浮层动效 4.2、添加背景动画 目录 1、从最基本的页面开始 2、添加图像/浮层部分 3、位置调整 4、添加动效 4.1、添加浮层动效 4.2、添加背景动画 5、总结 根据前面css的学习&a…

喜讯!安全狗荣获“2023年网络安全技术支撑优秀单位”称号

6月6日&#xff0c;由中共厦门市委网络安全和信息化委员会办公室&#xff08;以下简称“厦门市委网信办”&#xff09;主办的2023年网络安全技术支撑优秀单位颁奖仪式在厦门成功举行。 作为国内云原生安全领导厂商&#xff0c;安全狗受邀出席此次活动。 会上&#xff0c;安全狗…

Spring两大核心思想 IoC和AoP

目录 ✨ 一、什么是IoC 1、定义 &#x1f38a; 2、IoC思想 &#x1f38a; 3、优势 &#x1f38a; 4、对象的管理 &#x1f38a; 存对象&#xff1a;Component 取对象&#xff1a;AutoWired ✨二、什么是DI 1、定义 &#x1f38a; 2、IoC和DI的关系&#x1f38a; 可…

【笔记】echarts图表的缩放和鼠标滚动冲突的处理解决方案

解决方案不是很好&#xff0c;来源于github的issue&#xff0c;官方提供了&#xff0c;组合键触发缩放的功能。 https://github.com/apache/echarts/issues/5769 https://echarts.apache.org/zh/option.html#dataZoom-inside.zoomOnMouseWheel dataZoom-inside.zoomOnMouseWhe…

【正点原子K210连载】第十四章 按键输入实验 摘自【正点原子】DNK210使用指南-CanMV版指南

1&#xff09;实验平台&#xff1a;正点原子ATK-DNK210开发板 2&#xff09;平台购买地址https://detail.tmall.com/item.htm?id731866264428 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/docs/boards/xiaoxitongban 第十四章 按键输入实…

数据结构与算法笔记:实战篇 - 剖析Redis常用数据类型对应的数据结构

概述 从本章开始&#xff0c;就进入实战篇的部分。这部分主要通过一些开源醒目、经典系统&#xff0c;真枪实弹地教你&#xff0c;如何将数据结构和算法应用到项目中。所以这部分的内容&#xff0c;更多的是知识点的回顾&#xff0c;相对于基础篇和高级篇&#xff0c;其实这部…

短视频电商源码如何选择

在数字时代的浪潮下&#xff0c;短视频电商以其直观、生动、互动性强的特点&#xff0c;迅速崛起成为电商行业的一股新势力。对于有志于进军短视频电商领域的创业者来说&#xff0c;选择一款合适的短视频电商源码至关重要。本文将从多个角度探讨如何选择短视频电商源码&#xf…

【每日刷题】Day78

【每日刷题】Day78 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1608. 特殊数组的特征值 - 力扣&#xff08;LeetCode&#xff09; 2. 1385. 两个数组间的距离值 - …

我的世界服务器-高版本服务器-MC服务器-生存服务器-RPG服务器-幻世星辰

生存为主&#xff0c;RPG乐趣为辅&#xff0c;重视每位玩家的建议&#xff0c;一起打造心目中的服务器&#xff0c;与小伙伴一起探险我的世界&#xff01; 服务器版本: 1.18.2 ~ 1.20.4 Q群&#xff1a; 338238381 服务器官网: 星辰毛毛雨-Minecraft高版本生存服务器我的世界…

JVM原理(八):JVM虚拟机工具之基础故障工具

这里主要介绍监视虚拟机运行状态和进行故障处理的工具 1. jsp:虚拟机进程状况工具 jsp命令格式&#xff1a; jsp [options] [hostid] jps远程查询虚拟机进程状态 2. jstat:虚拟机统计信息监视工具 jstat命令格式&#xff1a; jstat [option vmid [interval [s|ms] [count]…

计算机专业课面试常见问题-计算机网络篇

目录 1. 计算机网络分为哪 5 层&#xff1f; 2. TCP 协议简述&#xff1f; 3. TCP 和 UDP 的区别&#xff1f;->不同的应用场景&#xff1f; 4. 从浏览器输入网址到显示页…

Wireshark - tshark支持iptables提供数据包

tshark现在的数据包获取方式有两种&#xff0c;分别是读文件、网口监听&#xff08;af-packet原始套接字&#xff09;。两种方式在包获取上&#xff0c;都是通过读文件的形式&#xff1b;存在文件io操作&#xff0c;在专门处理大流量的情境下&#xff0c; 我们复用wireshark去做…