彻底搞懂「一切皆文件」的UNIX哲学

一、UINX哲学

  一切皆文件是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、 套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。

二、UNIX文件类型

  下面列举了UNIX中常用到的文件类型,其实除了普通文件以外,其他的其实都不是真正意义上的文件。
在这里插入图片描述

三、查看进程文件

  UNIX中提供一个文件作为我们对其操作的入口。有些文件我们甚至可以使用命令直接查看其内容。下面我们以查看进程文件为例子。

ubuntu@VM-0-4-ubuntu:~$ ps|grep 78415  #找到我们的例子进程
  78415 pts/0    00:00:00 test
ubuntu@VM-0-4-ubuntu:~$ cd /proc/      #进入proc中
ubuntu@VM-0-4-ubuntu:/proc$ ls         #找到对应pid的文件夹
1    17       3    608     663222  73937  74918  77582  91         diskstats    keys         mtrr          sys
10   18       333  6096    663223  73938  75     78     92         dma          key-users    net           sysrq-trigger
102  19       335  610     669     73939  75626  78415  920937     driver       kmsg         pagetypeinfo  sysvipc
105  2        337  61649   670     74     757    78712  920954     execdomains  kpagecgroup  partitions    thread-self
ubuntu@VM-0-4-ubuntu:/proc$ cd 78415/
ubuntu@VM-0-4-ubuntu:/proc/78415$ ls
arch_status  cmdline          exe      loginuid   mountstats  oom_score_adj  sched         stack    timers
attr         comm             fd       map_files  net         pagemap        schedstat     stat     timerslack_ns
autogroup    coredump_filter  fdinfo   maps       ns          patch_state    sessionid     statm    uid_map
auxv         cpuset           gid_map  mem        numa_maps   personality    setgroups     status   wchan
cgroup       cwd              io       mountinfo  oom_adj     projid_map     smaps         syscall
clear_refs   environ          limits   mounts     oom_score   root           smaps_rollup  task
ubuntu@VM-0-4-ubuntu:/proc/78415$ cd fd //查看本进程的所有文件描述符号
ubuntu@VM-0-4-ubuntu:/proc/78415/fd$ ll
total 0
dr-x------ 2 ubuntu ubuntu  0 Nov  8 23:02 ./
dr-xr-xr-x 9 ubuntu ubuntu  0 Nov  8 23:01 ../
lrwx------ 1 ubuntu ubuntu 64 Nov  8 23:04 0 -> /dev/pts/0
lrwx------ 1 ubuntu ubuntu 64 Nov  8 23:04 1 -> /dev/pts/0
lrwx------ 1 ubuntu ubuntu 64 Nov  8 23:04 2 -> /dev/pts/0
ubuntu@VM-0-4-ubuntu:/proc/78415$ cat smaps #可以通过该文件内存映射详细信息
5621b8cf0000-5621b8cf1000 r--p 00000000 fc:02 520197                     /home/ubuntu/test
Size:                  4 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         4 kB
...
netstat -anpt | grep 8888
lsof -p 27534 //用lsof查看该进程的所有文件描述符,其中的type字段就是表明它是什么类型,通过man losf 

四、Linux 文件描述符到底是什么?

  在编程中对上述的文件、设备、socket我们通常都可以使用open函数打开,open给我们返回一个fd(文件描述符),那么这个fd究竟是啥?

4.1 进程与文件描述符的关系

  一个 Linux 进程启动后,会在内核空间中创建一个 PCB 控制块,PCB 内部有一个文件描述符表(File descriptor table),记录着当前进程所有可用的文件描述符,也即当前进程所有打开的文件。
除了文件描述符表,系统还需要维护另外两张表:

  • 打开文件表(Open file table)
  • i-node 表(i-node table)

  文件描述符表每个进程都有一个,打开文件表和 i-node 表整个系统只有一个,它们三者之间的关系如下图所示。
在这里插入图片描述

4.2 文件描述符的本质

  从本质上讲,这三种表都是结构体数组,0、1、2、73、1976 等都是数组下标。表中不难看出文件描述符是进程文件描述符的数组。

  通过文件描述符,可以找到文件指针,从而进入打开文件表。该表存储了以下信息:

  • 文件偏移量,也就是文件内部指针偏移量。调用 read() 或者 write() 函数时,文件偏移量会自动更新,当然也可以使用 lseek() 直接修改。
  • 状态标志,比如只读模式、读写模式、追加模式、覆盖模式等。
  • i-node 表指针。

  打开文件表只是文件的中转站,通过打开文件表的 i-node 指针进入 i-node 表,该表包含了诸如以下的信息:

  • 文件类型,例如常规文件、套接字或 FIFO。
  • 文件大小。
  • 时间戳,比如创建时间、更新时间。
  • 文件锁。

4.3几种文件描述符情景

  • 1、同一个进程的不同文件描述符可以指向同一个文件;(可能是通过调用 dup()、dup2()、fcntl() 或者对同一个文件多次调用了 open() 函数形成的。 )
  • 2、不同进程可以拥有相同的文件描述符;(描述符正好分配到与其他进程打开该文件的描述符一样)
  • 3、不同进程的同一个文件描述符可以指向不同的文件(一般也是这样,除了 0、1、2 这三个特殊的文件);
  • 4、不同进程的不同文件描述符也可以指向同一个文件。(每个进程各自对同一个文件发起了 open() 调用。同一个进程两次打开同一个文件,也会发生类似情况)

4.4 socket 文件描述符

  通过上面的知识,我们可以知道socket其实也是个文件,只不过这个文件用来进行网络通信的。我们获得sokcet的fd后,通过fd作为参数调用其他函数达到通信的目的。
  fd本质上更像win中的句柄,是内核提供给用户来安全地操作文件的标识,不像指针,拥有了指针后你能瞎JB改。拥有了描述符后,你只能传入描述符给特定的接口,实际操作由内核读取用户输入的参数后来安全地执行。

五、思考

1、文件的个数有何限制,文件描述符的个数有限制吗?

免责申明:本文是根据网上多篇文章加上自己的理解整合而成,如有使用不妥之处还望告知。

参考:

http://m.biancheng.net/view/3066.html
https://www.zhihu.com/question/288808056/answer/463060065
https://www.cnblogs.com/bravery/archive/2012/06/27/2560611.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值