为什么进程中的fd总是从3开始分配?

我们常说:进程是资源分配的基本单位

首先,每个进程在创建时会被分配独立的资源,比如内存空间、文件描述符、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 内核采用 最小可用整数优先分配 的策略:

  1. 当进程请求打开文件(如通过 open()socket() 等系统调用)时,内核会扫描当前进程的 fd 表。
  2. 选择当前未被占用的最小整数 作为新 fd。
  3. 若用户未显式关闭标准输入/输出/错误(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,并设置 errnoEMFILE
  • 服务崩溃或拒绝请求:常见于高并发服务(如 Web 服务器、数据库),导致无法处理新连接或文件操作。
  • 资源泄漏风险:若未正确处理错误,可能引发内存泄漏或僵尸连接。

3、修改限制

方法 1:临时修改(仅当前会话有效)
# 修改软限制(需不超过硬限制)
ulimit -n 65535
方法 2:永久修改(用户级)
  1. 编辑 /etc/security/limits.conf
  • sudo nano /etc/security/limits.conf
    
  • 添加以下内容(以用户 ubuntu 为例):
  1. ubuntu soft nofile 65535   # 软限制
    ubuntu hard nofile 1048576  # 硬限制
    
  2. 重启会话或重新登录生效。
方法 3:永久修改(系统级)
  1. 编辑 /etc/sysctl.conf
  • sudo nano /etc/sysctl.conf
    
  • 添加或调整全局最大 fd 限制:
  • fs.file-max = 2097152
    
  • 应用配置:
  • sudo sysctl -p

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值