文件描述符到底是啥?

在平时的 Android 开发中,你与文件描述符打过交道吗?一些知识点会涉及到文件描述符,比如:

  • mmap 函数的文件描述符参数

  • epoll 机制对文件描述符的限制

这时,如果让你说说对文件描述符的了解,你能回答上来吗?

不了解也没关系,集中注意力,我们一起来搞定它!

基础概念

Linux 中一切都可以看作文件,包括普通文件、链接文件、Socket 以及设备驱动等,对其进行相关操作时,都可能会创建对应的文件描述符。

文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,用于指代被打开的文件,对文件所有 I/O 操作相关的系统调用都需要通过文件描述符。

与文件的关系

下图为 Linux 系统中的三种表:

进程级别的文件描述符表:内核为每个进程维护一个文件描述符表,该表记录了文件描述符的相关信息,包括文件描述符、指向打开文件表中记录的指针。

系统级别的打开文件表:内核对所有打开文件维护了一个进程共享的打开文件描述表,表中存储了处于打开状态文件的相关信息,包括文件类型、访问权限、文件操作函数(file_operations)等。

系统级别的 i-node 表:i-node 结构体记录了文件相关的信息,包括文件长度,文件所在设备,文件物理位置,创建、修改和更新时间等,"ls -i" 命令可以查看文件 i-node 节点

查看文件描述符资源

文件描述符是一种系统资源,可以通过以下命令来查看文件描述符的上限:

script
1
2
3
4
5
6
7
8
9
10
11
#查看所有进程允许打开的最大 fd 数量
126|generic_x86:/ # cat /proc/sys/fs/file-max
174139

#查看所有进程已经打开的 fd 数量以及允许的最大数量
generic_x86:/ # cat /proc/sys/fs/file-nr
11040   0       174139

#查看单个进程允许打开的最大 fd 数量.
generic_x86:/ # ulimit -n
32768

也可以查看某进程当前已使用的 fd :

script
1
2
3
4
5
6
7
8
9
10
#查看某进程(进程 id 为 15077)已经打开的 fd
generic_x86:/ # ls -l /proc/15077/fd/
total 0
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 0 -> /dev/null
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 1 -> /dev/null
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 35 -> /dev/binder
lrwx------ 1 u0_a136 u0_a136 64 2020-04-09 01:01 44 -> socket:[780404]
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 55 -> /dev/ashmem
lrwx------ 1 u0_a136 u0_a136 64 2020-04-15 23:04 60 -> /dev/ashmem
...

上图中是一个 Android 应用进程,所以能看到 ashmem、binder 等 Android 特有设备文件相关的 fd 。

文件描述符的上限

来看一个实际打开磁盘文件的例子:

1
2
File file = new File(getCacheDir(), "testFdFile");
FileOutputStream out = new FileOutputStream(file);

执行上面代码后会申请一个对应的 fd:

script
1
2
3
4
# ls -l /proc/{pid}/fd/
...
l-wx------ u0_a55   u0_a55  2020-04-16 00:24 995 ->
                /data/data/com.example.test/cache/testFdFile
...

实际开发中,可能会遇到 fd 资源超过上限导致的 "Too many open files" 之类的问题,一般都是因为没有及时释放掉 fd,比如上面代码中 FileOutputStream 没有关闭,若循环执行超过单个进程允许打开的最大 fd 数量,程序就会出现异常。

END

推荐阅读

Application 这是一道送分题

谈谈你对 binder 的理解?

你真的懂 Context 吗?

关注我

助你升职加薪

Android 面试官

点亮在看,年薪百万!

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值