文件描述符简介
在linux系统中,一切皆文件,当进程打开现有文件或者创建新文件时,内核向进程返回一个文件描述符,文件描述符在形式上是一个非负整数,实际上它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。所有执行io操作的系统调用都会通过文件描述符执行。
文件描述符和进程的关系
系统为了维护文件描述符,建立了三个表:
image.png image.png
如上图所示:
- 在进程A中,文件描述符1和30都指向了同一个打开的文件句柄(#23),这可能是该进程多次执行打开操作。
- 进程A中的文件描述符2和进程B的文件描述符2都指向了同一个打开的文件句柄(#73),这种情况有几种可能,1.进程A和进程B可能是父子进程关系;2.进程A和进程B打开了同一个文件,且文件描述符相同(低概率事件=_=);3.A、B中某个进程通过UNIX域套接字将一个打开的文件描述符传递给另一个进程。
- 进程A的描述符0和进程B的描述符3分别指向不同的打开文件句柄,但这些句柄均指向i-node表的相同条目(#1936),换言之,指向同一个文件。发生这种情况是因为每个进程各自对同一个文件发起了打开请求。同一个进程两次打开同一个文件,也会发生类似情况。
命令示例
一个常见命令:
我们在linux下经常会碰到: nohup command>/dev/null 2>&1 & 这样形式的命令,我们把这条命令分解下:
- nohup 表示当前用户和系统的会话下的进程忽略相应hup消息。
- & 表示该命令以后台job的形式运行
- /dev/null 表示一个空设备, command的执行结果重定向到空设备中,也就是不显示任何信息。
- 2>&1 : 首先command > /dev/null 这条命令是一个缩写版,对于一个重定向命令,肯定是a>b这种形式, command > /dev/null 相当于执行了command 1 > /dev/null ,执行command产生了标准输出stdout(用1表示),重定向到/dev/null的设备文件中。对于2>&1,2是标准错误,1是标准输出,那么这条命令不就是相当于把标准错误重定向到标准输出么。等等是&1而不是1,这里&是什么?这里&相当于等效于标准输出,这里有点不好理解,先看下面。
command>a 2>a 与 command>a 2>&1的区别
通过上面的分析,command>a 2>&1等价于command 1>a 2>&1可以理解为执行command产生的标准输出重定向到文件a中,标准错误也重定向到文件a中,那么是否就说 command 1>a 2>&1等价于command 1>a 2>a呢,command 1>1 2>&1 与command 1>a 2>a还是有区别的,前者只打开一次文件a, 后者会打开文件两次,并导致stdout被stderr覆盖。**&1的含义可以理解为标准输出的引用, 引用的就是重定向标准输出产生打开的a。
例子说明
/test.sh
#!/bin/sh
t
date
chmod +x test.sh为test.sh增加执行权限。这里我们弄了两条命令,其中t指令并不存在,执行会报错,会输出到stderr。date能正常执行,执行会输出当前时间,会输出到stdout。
我们发现stderr并没有被重定向到res1.log中,stderr被打印到了屏幕上。这也进一步证明了上面说的./test.sh > res1.log等价于./test.sh 1>res1.log
执行./test.sh>res2.log 2>&1结果为
这次我们发现stdout和stderr都被重定向到了res2.log中了。上面我们未对stderr也就是2说明如何输出,stderr就输出到了屏 幕上,这里我们不仅对stdout进行说明,重定向到res2.log中,对标准错误也进行了说明,让其重定向到res2.log的引用即 res2.log的文件描述符中。
@ubuntu:~$ bash test.sh 1>test.log 2>&1
@ubuntu:~$ cat test.log
test.sh: line 2: t: command not found
Tue Nov 27 15:56:02 PST 2018
@ubuntu:~$ bash test.sh 1>test.log 2>test.log
@ubuntu:~$ cat test.log
Tue Nov 27 15:56:47 PST 2018
ot found // 被覆盖了
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
$ command > file 2>&1
或者
$ command >> file 2>&1
查看该进程的限制
ps -ef | grep redis
cat /proc/16943/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 3731 3731 processes
Max open files 10032 10032 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 3731 3731 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
在 Max open files 那一行,可以看到当前设置中最大文件描述符的数量为10032
- soft 指的是当前系统生效的设置值
- hard 指的是系统中所能设定的最大值
查看该进程占用了多少个文件描述符
ll /proc/16943/fd/
total 0
dr-x------ 2 wusong wusong 0 Nov 27 07:42 ./
dr-xr-xr-x 9 wusong wusong 0 Nov 27 07:42 ../
lrwx------ 1 wusong wusong 64 Nov 27 07:46 0 -> /dev/pts/8
lrwx------ 1 wusong wusong 64 Nov 27 07:46 1 -> /dev/pts/8
lrwx------ 1 wusong wusong 64 Nov 27 07:42 2 -> /dev/pts/8
lrwx------ 1 wusong wusong 64 Nov 27 07:46 3 -> anon_inode:[eventpoll]
lrwx------ 1 wusong wusong 64 Nov 27 07:46 4 -> socket:[329365]
lrwx------ 1 wusong wusong 64 Nov 27 07:46 5 -> socket:[329366]
实际应用过程中,如果出现“Too many open files” , 可以通过增大进程可用的文件描述符数量来解决,但往往故事不会这样结束,很多时候,并不是因为进程可用的文件描述符过少,而是因为程序bug,打开了大量的文件连接(web连接也会占用文件描述符)而没有释放。程序申请的资源在用完后及时释放,才是解决“Too many open files”的根本之道。
网友评论