我们常说:进程是资源分配的基本单位
首先,每个进程在创建时会被分配独立的资源,比如内存空间、文件描述符、CPU时间片等。这里的“资源”包括硬件资源(CPU、内存、I/O设备)和软件资源(如文件、信号量等)。
这里先声明一下:进程是 CPU 时间分配的基本单位(尽管线程是执行的最小单元,但线程所属的进程整体参与调度)。
好了,进入正题,文件描述符fd也是每个进程独立一套。fd是一个int型,按理来说,fd应该是从0开始的,执行代码后发现,进程中代码创建的第一个fd是3。
#include <iostream>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(){
int fd1 = open("./test1.cpp", O_RDONLY | O_CREAT, 0644);
printf("fd1 = %d\n", fd1); //fd = 3
int fd2 = open("./test2.cpp", O_RDONLY | O_CREAT, 0644);
printf("fd2 = %d\n", fd2); //fd = 4
int fd3 = open("./test3.cpp", O_RDONLY | O_CREAT, 0644);
printf("fd3 = %d\n", fd3); //fd = 5
getchar(); // 等待输入继续运行
close(fd1);
close(fd2);
close(fd3);
return 0;
}
可以在2个终端起分别起线程,发现输出都是3、4、5,说明:文件描述符fd也是每个进程独立一套。
那为什么fd是从3开始呢?
所有 Linux 进程在启动时默认会打开 3 个标准文件描述符:
- 0: 标准输入(
stdin
) - 1: 标准输出(
stdout
) - 2: 标准错误(
stderr
) 这些 fd 由 Shell 或进程启动器(如systemd
)自动分配,用于基础的输入输出操作。因此,用户程序首次创建新的 fd 时,内核会从 第一个可用的最小整数(3) 开始分配。
内核的 fd 分配策略
Linux 内核采用 最小可用整数优先分配 的策略:
- 当进程请求打开文件(如通过
open()
、socket()
等系统调用)时,内核会扫描当前进程的 fd 表。 - 选择当前未被占用的最小整数 作为新 fd。
- 若用户未显式关闭标准输入/输出/错误(0/1/2),则新 fd 会从 3 开始,依次递增为 4、5、6 等。
#include <unistd.h>
#include <fcntl.h>
int main() {
close(0); // 关闭 stdin(fd 0)
int fd1 = open("file1.txt", O_RDONLY); // 分配 fd 0
int fd2 = open("file2.txt", O_RDONLY); // 分配 fd 3(假设 fd 1/2 仍被占用)
return 0;
}
那fd最大被限制成多少?超过该限定,后果是什么?能否修改限定及如何修改?
1、查看当前限制
通过以下命令查看当前用户的 fd 限制:
# 查看软限制(实际生效值)
ulimit -Sn
# 查看硬限制(最大允许值)
ulimit -Hn
输出示例:
1024 # 默认软限制通常为 1024
1048576 # 硬限制可能为 1048576(不同系统有差异)
2、超过限制后果
当进程打开的 fd 数量超过 ulimit
限制时,系统会抛出 EMFILE
(Too many open files)错误,具体表现为:
- 系统调用失败:
open()
、socket()
、accept()
等函数返回-1
,并设置errno
为EMFILE
。 - 服务崩溃或拒绝请求:常见于高并发服务(如 Web 服务器、数据库),导致无法处理新连接或文件操作。
- 资源泄漏风险:若未正确处理错误,可能引发内存泄漏或僵尸连接。
3、修改限制
方法 1:临时修改(仅当前会话有效)
# 修改软限制(需不超过硬限制)
ulimit -n 65535
方法 2:永久修改(用户级)
- 编辑
/etc/security/limits.conf
:
-
sudo nano /etc/security/limits.conf
- 添加以下内容(以用户
ubuntu
为例):
-
ubuntu soft nofile 65535 # 软限制 ubuntu hard nofile 1048576 # 硬限制
- 重启会话或重新登录生效。
方法 3:永久修改(系统级)
- 编辑
/etc/sysctl.conf
:
-
sudo nano /etc/sysctl.conf
- 添加或调整全局最大 fd 限制:
-
fs.file-max = 2097152
- 应用配置:
-
sudo sysctl -p