当前位置 : 主页 > 操作系统 > centos >

深入理解文件描述符

来源:互联网 收集:自由互联 发布时间:2022-06-20
1. 背景 之前一直对文件描述符,重定向符号的含义不是很清楚。今天整理了下文件描述符的背景知识,并实际操作了文件描述符,对其理解有了更深入的认识。 2. 文件元数据Inode Inod

1. 背景

之前一直对文件描述符,重定向符号的含义不是很清楚。今天整理了下文件描述符的背景知识,并实际操作了文件描述符,对其理解有了更深入的认识。

2. 文件元数据Inode

Inode保存文件的元数据。分别是:Inode编号、文件权限、文件的拥有者的UID、文件所属组的GID、硬链接数、文件的大小、文件的间戳、指向磁盘文件的数据块指针等。其信息如下图所示:

Inode信息.png

通过linux的stat命令可以查看文件的inode信息:

image.png参数解释如下:

  • File:显示文件名
  • Size:显示文件大小
  • Blocks:文件使用的数据块总数
  • IO Block:IO块大小
  • regular file:文件类型(常规文件)
  • Device:设备编号
  • Inode:Inode号
  • Links:链接数
  • Access:文件的权限
  • Gid、Uid:文件所有权的Gid和Uid
  • access time:表示我们最后一次访问(仅仅是访问,没有改动)文件的时间
  • modify time:表示我们最后一次修改文件的时间
  • change time:表示我们最后一次对文件属性改变的时间,包括权限,大小,属性等等
  • Birth time : 文件创建时间,crtime,不过据查此属性linux已废弃,目前状态显示结果均为-

3. 目录与文件名

文件名并不是保存在Inode中,而是保存在父目录的block中。通过父目录的Inode可以定位到block,在block中可以找到父目录包含的子文件名与Inode的对应关系。

目录与文件名.png

4. 文件描述符

在linux中,内核通过inode来找到每个文件,但一个文件可以被许多用户同时打开或一个用户同时打开多次。这就有一个问题,如何管理文件的当前位移量,因为可能每个用户打开文件后进行的操作都不一样,这样文件位移量也不同,当然还有其他的一些问题。所以linux又搞了一个文件描述符(file descriptor)这个东西,来分别为每一个用户服务。每个用户每次打开一个文件,就产生一个文件描述符,多次打开就产生多个文件描述符,一一对应,不管是同一个用户,还是多个用户。该文件描述符就记录了当前打开的文件的偏移量等数据。所以一个i节点可以有0个或多个文件描述符。多个文件描述符可以对应一个i节点。

打开现有文件或新建一个文件时,内核会返回一个文件描述符,文件描述符用来指定已打开的文件。内核维护了文件描述符表、打开文件表和Inode表,描述了如何通过文件描述符找到文件的物理位置。

  • 文件描述符表维护进程打开的文件。一条记录为一个句柄。
  • 打开文件表维护所有打开的文件。一条记录为一个句柄。
  • Inode表维护所有Inode的元数据信息。

每个表的字段内容如下:image.png

3个表的调用关系如下:

进程描述符到Inode.png

5. 重定向符号

重定向符号有<、>、<>。可以通过以下例子理解:

  • 2&gt;&1&gt;/dev/null:先定义2>&1,此时表示错误输出和标准输出都打印到屏幕上;再定义1>/dev/null,表示标准输出丢弃。

  • &gt;/dev/null 2&gt;&1:先定义1>/dev/null,表示标准输出丢弃;再定义2>&1,由于标准输出已经表示要丢弃了,此时表示错误输出也丢弃。

效果如下:

image.png

备注:& 发信号通知 Bash 1 是目标文件描述符。

例如:

  • cat file等价于cat 0< file,即将file文件内容作为标准输入,即以只读方式打开file文件,cat则打印该输入。
  • cat 0<> file表示以读写方式打开file文件,由于0是stdin,无法产生输出,因此cat 0<> file和 cat 0< file无区别。注意:<>是一个重定向字符,表示将将file文件的输入输出重定向到文件描述符0中。

6. 文件操作底层流程

6.1 打开文件

  • 系统的文件打开表增加一条句柄,描述打开的文件信息,(若已有其他进程打开,则直接在打开计数器+1即可);同时也复制给进程的文件描述符表。
  • 执行打开命令后,并不会将文件的数据写入到内存,只是对几张表的操作。
  • 6.2 关闭文件

  • 将进程的文件描述符表句柄删除。
  • 回收分配给该文件的内存空间资源。
  • 系统级的打开文件表计算器count-1,若count=0,则删除句柄。
  • 7. 文件描述符实践

    目的:读写socket,向百度发送HTTP请求,并获得百度的响应。

    7.1 建立链接

    创建一个socket文件,打开该socket文件,在文件描述符表中创建一个句柄,使用文件描述符表示该句柄:

    //当指定目录为/dev/tcp/www.baidu.com/80时,触发内核机制,本机与www.baidu.com的80端口建立socket连接;socket是一个文件,将socket文件的输入输出重定向到文件描述符8中。<>是一个符号,表示以读写方式打开socket文件。 exec 8<> /dev/tcp/www.baidu.com/80

    查看进程的文件描述符,发现已经创建了8这个文件描述符:image.png

    命令解释:

    exec:  shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行。  因此,如果在一个shell里面执行exec ls;那么,当列出了当前目录后,这个shell就自己退出了,因为这个shell进程已被替换为仅仅执行ls命令的一个进程,执行结束自然也就退出了。  为了避免这个影响我们的使用,一般将exec命令放到一个shell脚本里面,用主脚本调用这个脚本,调用点处可以用bash a.sh,(a.sh就是存放该命令的脚本),这样会为a.sh建立一个sub shell去执行,当执行到exec后,该子脚本进程就被替换成了相应的exec的命令。  source命令或者”.”,不会为脚本新建shell,而只是将脚本包含的命令在当前shell执行。  不过,要注意一个例外,当exec命令来对文件描述符操作的时候,就不会替换shell,而且操作完成后,还会继续执行接下来的命令。

    exec总结:image.png

    7.2 发送请求

    echo -e "GET / HTTP/1.0\n" >&8

    解释:

    • echo -e表示要转译\n为一个空行。
    • &gt;&8等价于1&gt;&8,表示标准输出重定向到文件描述符8中,即重定向到socket文件中。

    7.3 获取响应

    cat <&8

    解释:

    • cat <&8,等价于cat 0<&8:表示将文件描述符8的内容作为标准输入,输出到标准输出设备(即屏幕)上。即将socket文件内容打印到屏幕上。

    百度返回的信息如下:

    image.png

    上一篇:Kubernetes安装Metrics数据采集插件
    下一篇:没有了
    网友评论