美文网首页
文件描述符

文件描述符

作者: tracy_668 | 来源:发表于2018-11-28 07:20 被阅读0次

文件描述符简介

在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

  1. soft 指的是当前系统生效的设置值
  2. 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”的根本之道。

相关文章

  • 第三章 文件I/O

    文件描述符 所有打开的文件都通过文件描述符引用。操作(读写)该文件描述符就相当于操作该文件。文件描述符是一个非负的...

  • 第三章 文件IO

    对于内核而言,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数文件描述符标准符号常量文件描述符0标准输...

  • ios进阶路线 shell脚本语言基础教程(四)

    上篇我们讲了文件描述符还有自定义文件描述符,补充一下如何关闭自定义的文件描述符 语法:exec 描述符>&- 案例...

  • Linux中文件描述符,重定向与标准输入输出

    Linux中文件描述符,重定向与标准输入输出 文件描述符:内核(kernel)利用文件描述符(file descr...

  • 文件I/O和记录锁

    文件描述符: 文件描述符是一个非负整数,所有打开的文件都通过文件描述符引用。按照惯例:0(STDIN_FILENO...

  • 认识安卓的文件描述符FileDescriptor

    理解文件描述符 文件描述符(FileDescriptor) 这是Unix/Linux系统文件操作的相关概念,And...

  • ulimit ps dmesg which stat 命令小结

    ulimit 设置查看文件描述符命令 ulimit -n查看文件描述符 ulimit -SHn 65535设置文件...

  • 文件描述符

    内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件...

  • Shell--呈现数据

    文件描述符 用stdout和stderr文件描述符来在多个位置生成输出,重定向相应的文件描述符 临时重定向 在脚本...

  • Linux I\O总结 -- 基础概念篇

    文件描述符 0, 1, 2 文件描述符(fd) 0 is standard in (stdin),1 is sta...

网友评论

      本文标题:文件描述符

      本文链接:https://www.haomeiwen.com/subject/igloqqtx.html