前言
在 Linux 系统中一切皆文件,当一个进程打开或者创建一个新的文件时,系统内核会向该进程返回一个文件描述符(File Descriptor,简称:Fd);该文件描述符是内核为了高效管理被打开文件所创建的索引。该索引指向被打开的文件,关于该文件的所有I/O操作都会通过该文件描述符调用。
当一个进程启动后,会创建一个 PCB
控制块,而 PCB 内部有一个文件描述符表:File descriptor table;记录着当前进程所有可用的文件描述符,即当前进程所有打开的文件。
除此之外系统还要维护另外两张表:打开文件表(Open file table)、i-node 表(i-node table),这两个表整个系统只有一个,三者关系如下:
I/O操作流程
通过 Fd
找到文件指针,通过该指针进入打开文件表,该表存储了以下信息:
1、文件偏移量,也就是文件内部指针偏移量。调用 read() 或者 write() 函数时,文件偏移量会自动更新,当然也可以使用 lseek() 直接修改。
2、状态标志,比如只读模式、读写模式、追加模式、覆盖模式等。
3、i-node 表指针。
要想真正读写文件,还得通过打开文件表的 i-node 指针进入 i-node 表,该表包含了诸如以下的信息:
1、文件类型,例如常规文件、套接字或 FIFO。
2、文件大小。
3、时间戳,比如创建时间、更新时间。
4、文件锁。
实操
1、查看进程可打开最大文件数(即PCB表最大数量)
ulimit -n
# 临时设置进程最大打开文件数
ulimit -n <num>
2、查看某个进程的信息
# 1、获取进程ID
ps aux | grep sshd
# root 784 0.0 0.2 16132 9156 ? Ss 2022 5:29 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
# 2、查看进程信息
/proc/N/cmdline # 进程启动命令
/proc/N/cwd # 链接到进程当前工作目录
/proc/N/environ # 进程环境变量列表
/proc/N/exe # 链接到进程的执行命令文件
/proc/N/fd # 包含进程相关的所有的文件描述符
/proc/N/maps # 与进程相关的内存映射信息
/proc/N/mem # 指代进程持有的内存,不可读
/proc/N/root # 链接到进程的根目录
/proc/N/stat # 进程的状态
/proc/N/statm # 进程使用的内存的状态
/proc/N/status # 进程状态信息,比stat/statm更具可读性
/proc/N/limits # 查看该进程的限制
3、查看系统打开的文件描述符数量
cat /proc/sys/fs/file-nr
8992 0 378170
# 已打开的,已释放的(不再使用),最大可打开的(file-max)