Linux的文件描述符详解程序员

(1).文件描述符的定义

  文件描述符是内核为了高效管理已被打开的文件所创建的索引,用于指向被打开的文件,所有执行I/O操作的系统调用都通过文件描述符;文件描述符是一个简单的非负整数,用以表明每个被进程打开的文件。程序刚刚启动时,第一个打开的文件是0,第二个是1,以此类推。也可以理解为文件的身份ID。

  用户通过操作系统处理信息的过程中,使用的交互设备文件(键盘,鼠标,显示器)

文件描述符 通道名 描述 默认连接 用途
0 stdin 标准输入 键盘 read only
1 stdout 标准输出 终端 write only
2 stderr 标准错误 终端 write only
3以上 filename 其他文件 none read and/or write

标准输入输出说明

stdin,标准输入,默认设备是键盘,文件编号为0

stdout,标准输出,默认设备是显示器,文件编号为1,也可以重定向到文件

stderr,标准错误,默认设备是显示器,文件编号为2,也可以重定向到文件

(2).查看一个进程打开了哪些文件

语法: ll /proc/[进程ID]/fd

[[email protected] ~]$ vim a.txt  
 
[1]+  已停止               vim a.txt 
[[email protected] ~]$ ps -aux | grep vim 
xf        11990  0.6  0.2 151796  5396 pts/0    T    16:37   0:00 vim a.txt 
xf        11998  0.0  0.0 112724   988 pts/0    S+   16:37   0:00 grep --color=auto vim 
[[email protected] ~]$ ll /proc/11990/fd 
总用量 0 
lrwx------. 1 xf xf 64 2月  21 16:37 0 -> /dev/pts/0 
lrwx------. 1 xf xf 64 2月  21 16:37 1 -> /dev/pts/0 
lrwx------. 1 xf xf 64 2月  21 16:37 2 -> /dev/pts/0 
lrwx------. 1 xf xf 64 2月  21 16:37 4 -> /home/xf/.a.txt.swp 

  0、1、2也就是宏STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO。

  /proc/[进程ID]/fd这个目录专门用于存放文件描述符

  另外还可以使用ls -l /proc/self/fd。

(3).文件描述符限制

  Linux中最大文件描述符的限制有两个方面,一个是用户级限制,一个是系统级限制。

  但是,查看Linux文件描述符限制有三种方式:

[[email protected] ~]$ sysctl -a | grep file-max    //过滤一下,不然参数太多不好找 
sysctl: permission denied on key 'fs.protected_hardlinks' 
sysctl: permission denied on key 'fs.protected_symlinks' 
fs.file-max = 196630    //file-max其实是红色字体 
sysctl: permission denied on key 'kernel.cad_pid' 
sysctl: permission denied on key 'kernel.usermodehelper.bset' 
sysctl: permission denied on key 'kernel.usermodehelper.inheritable' 
sysctl: permission denied on key 'net.core.bpf_jit_harden' 
sysctl: permission denied on key 'net.ipv4.tcp_fastopen_key' 
sysctl: permission denied on key 'net.ipv6.conf.all.stable_secret' 
sysctl: permission denied on key 'net.ipv6.conf.default.stable_secret' 
sysctl: permission denied on key 'net.ipv6.conf.ens33.stable_secret' 
sysctl: permission denied on key 'net.ipv6.conf.lo.stable_secret' 
sysctl: permission denied on key 'net.ipv6.conf.virbr0.stable_secret' 
sysctl: permission denied on key 'net.ipv6.conf.virbr0-nic.stable_secret' 
sysctl: permission denied on key 'vm.mmap_rnd_bits' 
sysctl: permission denied on key 'vm.mmap_rnd_compat_bits' 
[[email protected] ~]$ cat /proc/sys/fs/file-max  
196630 
[[email protected] ~]$ ulimit -n 
1024

  用户级限制:ulimit命令看到的是用户级的最大文件描述符限制,也就是说每一个用户登录后执行的程序占用文件描述符的总数不能超过这个限制

  系统级限制:sysctl命令与proc文件系统中查看到的数值是一样的,这属于系统级限制,它是限制所有用户打开文件描述符的总和。

1)修改用户级限制

  临时修改上限,只对当前Shell有效

[[email protected] ~]$ ulimit -n  //-n打开文件描述符的最大个数 
1024 
[[email protected] ~]$ ulimit -Sn  //-S是软性限额 
1024 
[[email protected] ~]$ ulimit -Hn  //-H是硬性限额 
4096 
[[email protected] ~]$ ulimit -n 2048  //可以看到在没有指定-S和-H选项时修改会同时修改软性和硬性限额 
[[email protected] ~]$ ulimit -n 
2048 
[[email protected] ~]$ ulimit -Sn 
2048 
[[email protected] ~]$ ulimit -Hn 
2048 
[[email protected] ~]$ ulimit -Hn 4096 
bash: ulimit: open files: 无法修改 limit 值: 不允许的操作

  注意:硬性限额在设置好不能增加,除非使用root用户;软性限额可以增加,直到与硬性限额相等。

  永久修改需要使用root用户编辑/etc/security/limits.conf。里面会有详细说明。修改文件描述符,应该注意<item>字段下是否存在nofile字段,如果存在请修改,不存在请添加。

*    hard    nofile    4096 
*    soft    nofile    2048 

  添加完成后保存退出,重启系统,即可生效。

  注意:soft一行中的<value>字段要小于或等于hard一行中的<value>字段。

2)修改系统限制级

  修改系统限制级,不管是临时修改还是永久修改都需要使用root用户。

  临时修改,重启后无效

//可以使用sysctl命令修改 
[[email protected] ~]# sysctl -w fs.file-max=8192 
fs.file-max = 8192 
[[email protected] ~]# sysctl -a | grep fs.file-max 
fs.file-max = 8192 
sysctl: reading key "net.ipv6.conf.all.stable_secret" 
sysctl: reading key "net.ipv6.conf.default.stable_secret" 
sysctl: reading key "net.ipv6.conf.ens33.stable_secret" 
sysctl: reading key "net.ipv6.conf.lo.stable_secret" 
sysctl: reading key "net.ipv6.conf.virbr0.stable_secret" 
sysctl: reading key "net.ipv6.conf.virbr0-nic.stable_secret" 
[[email protected] ~]# cat /proc/sys/fs/file-max  
8192 
//也可以修改/proc/sys/fs/file-max文件 
[[email protected] ~]# cat >/proc/sys/fs/file-max <<EOF 
> 16384 
> EOF 
[[email protected] ~]# cat /proc/sys/fs/file-max  
16384 
[[email protected] ~]# sysctl -a | grep fs.file-max 
fs.file-max = 16384 
sysctl: reading key "net.ipv6.conf.all.stable_secret" 
sysctl: reading key "net.ipv6.conf.default.stable_secret" 
sysctl: reading key "net.ipv6.conf.ens33.stable_secret" 
sysctl: reading key "net.ipv6.conf.lo.stable_secret" 
sysctl: reading key "net.ipv6.conf.virbr0.stable_secret" 
sysctl: reading key "net.ipv6.conf.virbr0-nic.stable_secret" 

  永久修改需要进入到/etc/sysctl.conf中,修改或添加fs.file-max=value,然后重启系统或使用sysctl -p重新读取参数。

[[email protected] ~]# vim /etc/sysctl.conf 
[[email protected] ~]# sysctl -a | grep fs.file-max 
fs.file-max = 196630 
sysctl: reading key "net.ipv6.conf.all.stable_secret" 
sysctl: reading key "net.ipv6.conf.default.stable_secret" 
sysctl: reading key "net.ipv6.conf.ens33.stable_secret" 
sysctl: reading key "net.ipv6.conf.lo.stable_secret" 
sysctl: reading key "net.ipv6.conf.virbr0.stable_secret" 
sysctl: reading key "net.ipv6.conf.virbr0-nic.stable_secret" 
[[email protected] ~]# sysctl -p 
fs.file-max = 10000 
[[email protected] ~]# sysctl -a | grep fs.file-max 
fs.file-max = 10000 
sysctl: reading key "net.ipv6.conf.all.stable_secret" 
sysctl: reading key "net.ipv6.conf.default.stable_secret" 
sysctl: reading key "net.ipv6.conf.ens33.stable_secret" 
sysctl: reading key "net.ipv6.conf.lo.stable_secret" 
sysctl: reading key "net.ipv6.conf.virbr0.stable_secret" 
sysctl: reading key "net.ipv6.conf.virbr0-nic.stable_secret" 

  注:有些人说root用户使用命令sysctl -w fs.file-max=10000,接着sysctl -p就可永久修改。可是我试下来重启系统后就会还原,有时间的可以试一下。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/2821.html

(0)
上一篇 2021年7月16日
下一篇 2021年7月16日

相关推荐

发表回复

登录后才能评论