​​​​​​​             ​​​​​​​ 

感谢各位 点赞 收藏 评论 三连支持

本文章收录于专栏【Linux系统编程】

❀希望能对大家有所帮助❀

本文章由 风君子吖 原创

​​​​​​​        ​​​​​​​        ​​​​​​​               

前言

之前我们学习回顾了C语言文件操作的接口函数,并且学会了使用系统给我们提供的文件操作接口函数,

还知道了许多的概念,对于语言层面上的接口函数,它们在底层必然会对系统接口函数进行封装,这不仅便于我们使用,而且还实现了语言的跨平台性。

而学习系统调用接口,就是学习语言层面上我们一些我们无法理解的东西,能够更好的了解底层,再今后的学习更加受益匪浅!

而在Linux中,万物皆文件,所以不仅仅只是磁盘上存储的文件叫文件,我们的各种硬件也能被称之为文件,所以,我们调用系统提供的文件操作函数也可以对硬件进行各种操作,当然,这种操作并不是我们用户层来操作的,而是进程经过OS之手来进行操作的,因为只有操作系统才有对硬件进行IO的权限!

上一篇文章,我们对于文件描述符fd进行了初步的了解,而今天,我们就来详细讲解文件描述符fd与整个文件体系的密切关系

文件描述符fd

想要理解文件描述符就得明白这样一个概念,怎么样的文件才会被给予文件描述符? 一台计算机中的磁盘上可能会有上万的文件,那么我们需要对所有的文件都进行管理吗? 肯定不能,所以,我们只能对被进程打开的文件进行管理,而这些文件也会被加载到内存中,而这些被打开的文件,就会被给予文件描述符。

上篇文章中,我们从打印的文件描述符来看,它似乎是一串连续的数字,并且我们打开的文件的描述符都是从3开始依次增加的,这是因为在系统在进程运行时,会默认打开三个文件,这些文件就是标准输入(0),标准输出(1),标准错误(2)。

从fd的结果来看 为什么是一串连续的数字,这有什么特殊的含义吗? 从我们之前的经验来看,一串连续的数字通常会联想到什么?   没错,就是数组下标,那么这跟数组下标真的有关系吗?如果真的是数组下标,那么有什么用,这就需要明白文件在内存中的体系结构。

文件体系结构(重点)

这里讲的文件体系结构指的是被进程打开的文件,而被进程打开的文件是要被加载的内存的,也就是要在内核中创建一个管理文件的数据结构,更重要的是,既然是被进程所打开,那么就需要被进程所管理起来。

而进程的管理模块是我们熟的不能再熟的PCB(process control block) ,那么有什么办法可以储存文件的几乎所有内容呢? -> 答案是struct 结构体 ,而这个结构体叫做struct file{...} ,这个结构体包含了一个文件的几乎所有内容。

但是一个进程只能打开一个文件吗?  肯定是不止的,光进程打开的默认三个文件标准输入输出、错误就有三个文件,所以一个进程是可以打开多个文件的,而进程与被打开的文件的比例就是1:n,所以我们就又需要一个结构体来管理所有的打开的文件,这个结构体叫做files_struct,并且这个结构体是被存储于进程的PCB之中的,所以就有了这么一个对应关系

struct task_struct(PCB)->struct files_struct->struct file

files_struct储存多个struct file是通过一个指针数组来完成的,而这个指针数组,每个元素都是存储着struct* file,那么这个时候fd充当下标就再合适不过了!

重定向

对于fd文件描述符的作用我们已经知道了,它是被files_struct 用来找对应的文件的,那么我们来看下面比较有意思的现象。

先将fd为1的文件关闭,也就是标准输出文件关闭,然后再打开log.txt文件

[fengjunzi@VM-4-2-centos lesson14_fd]$ ./myfile
[fengjunzi@VM-4-2-centos lesson14_fd]$ ll
total 24
-rw-rw-r-- 1 fengjunzi fengjunzi   22 Jun  7 18:27 log.txt
-rw-rw-r-- 1 fengjunzi fengjunzi   65 Jun  7 13:03 Makefile
-rwxrwxr-x 1 fengjunzi fengjunzi 8608 Jun  7 18:27 myfile
-rw-rw-r-- 1 fengjunzi fengjunzi  340 Jun  7 18:27 myfile.c
[fengjunzi@VM-4-2-centos lesson14_fd]$ cat log.txt
hello world
hello 123

这个时候运行程序发现并没有打印hello world 和 hello 123 在屏幕上,并且再查看log.txt的内容,发现竟然写到了log.txt 里面,这是怎么一回事?

close(1)关闭的是标准输出,那么关闭的是stdout吗?  这是不准确的,因为stdout是FILE*类型,而FILE是C语言定义的,那么系统是认fd还是认FILE? 而stdout要跟标准输出要有关联,那么C语言一定对stdout进行了fd的封装,并且stdout的fd一定是1 ,所以这里我们虽然close(1),但是stdout仍然存在,且stdout的fd仍然是1,但是stdout已经不再指向的是标准输出了,那是指的什么?  ->  从结果来看,这时候的stdout指向的是log.txt文件。

为什么会指向log.txt?因为我们先关闭了fd = 1 ,而在我们打开新文件的时候,是会先从头检查fd_array是否存在空指针,如果有空指针,就会把该位置的fd分配给那个文件,所以这个时候log.txt就顶替了stdout的 fd,而printf,和fprintf无不是针对fd = 1 的文件进行写入!

那么这种现象叫做什么?是不是很像输出重定向?那么输出重定向的实现就是我们上面所写的那样吗? 不是,因为系统提供了一个接口来更好的实现这个功能!

而通过这种方式,我们如果先close(0),再调用scanf,是不是就相当于输入重定向了?

dup2系统调用

dup2() makes newfd be the copy of oldfd, closing newfd first if necessary, but note the following:*  If oldfd is not a valid file descriptor, then the call fails, and newfd is not closed.*  If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing, and returns newfd.

翻译过来就是使newfd被拷贝于oldfd,拷贝的是什么,当然是文件的内容,newfd指向的文件内容会被拷贝成oldfd的文件内容。

通过这个接口就能更好的实现输入、输出、追加重定向,因为如果使用上面的那种还需要关闭一个文件,更加麻烦。

输出重定向

追加重定向

输入重定向

总结

本篇文章,主要讲解了被打开的文件在内存内核中被存储的数据结构,详细讲解了其体系结构,并且讲解了fd文件描述符在整个体系结构的作用,用于作为下标访问对应文件内容。

还讲解了系统提供的dup2接口的作用,以及如何调用dup2 实现输入、输出、追加重定向。

但是,对于文件我们仍然有许多疑问,例如文件缓冲区,还有struct file 存储的一些什么标志性内容,这些我打算放在下一篇文章来进行详细讲解。

Linux - fd文件描述符和文件详解相关推荐

  1. linux文件描述符泄漏,文件描述符(fd)泄漏排查一篇就够了

    生产多次遇到文件描述符(fd)泄露相关的问题, 文件描述符泄漏一般引起 的现象是文件句柄数(封面图)/tcp alloc(上图)增长.文章分为两部分介绍文件描述符相关内容,第一部分介绍文件描述基础知识 ...

  2. linux进程文件描述符 vnode,Linux C编程详解:进程原理分析、文件描述符和文件记录表、文件句柄和文件原理...

    一.引言 文件操作是Linux C编程中其中的一项核心技术,实际上也相当重要,这里并不是说狭义上的那种文件操作,它也非常有助于理解和学习Linux系统.为什么这样说呢?因为在Unix/Linux的世界 ...

  3. 嵌入式Linux系统编程学习之九基于文件描述符的文件操作

    文章目录 前言 一.文件描述符 二.打开.创建和关闭文件 三.读写文件 四.改变文件大小 五.文件定位 六.原子操作 七.进一步理解文件描述符 八.文件描述符的复制 九.文件的锁定 十.获取文件信息 ...

  4. 在c语言中文件的指针是什么,C语言中文件描述符和文件指针的本质区别

    1,首先了解进程运行时默认打开的文件指针以及打开的文件 /* Standard streams. / extern struct _IO_FILE stdin; / Standard input st ...

  5. Linux系统编程——基于文件描述符的文件操作(1)

    概要: 打开.创建和关闭文件 读写文件 文件定位 获取文件信息 打开.创建和关闭文件 函数原型: #include <sys/types.h> //头文件 #include <sys ...

  6. (整理类)文件描述符,文件描述符标志,文件状态标志

    感谢和参考于(你们是我成长路上的最大助力!): Linux中文件描述符fd和文件指针flip的理解 文件描述符标志.文件状态标志 Linux编程–文件描述符fd PART 1 文件描述符:fd(fil ...

  7. UNIX中文件描述符和文件指针

    文件描述符 在C程序中,文件由文件指针或者文件描述符表示.ISO C的标准I/0库函数(fopen, fclose, fread, fwrite, fscanf, fprintf等)使用文件指针,UN ...

  8. 32 usb 配置描述符_USB协议详解第4讲(USB描述符标准配置描述符)

    关注+星标公众号,不错过精彩内容 编排 | 一个早起的程序员 一个早起的程序员 1 USB描述符USB描述符有设备描述符.标准配置描述符.接口描述符.端点描述符.字符串描述符,HID设备有HID描述符 ...

  9. linux c 文件指针 句柄(FILE*) 文件描述符(fd) 文件路径(filepath) 互相转换

    最近在linux下编程常需要对一些文件进行操作.有时不同的条件下,需要将文件指针/句柄(FILE*).文件描述符(fd)以及文件路径(filepath)进行相互转换,以满足实际的编程需要. 现简单的做 ...

最新文章

  1. Android之linux之基础建设之窗口系统
  2. 128条形码计算,利用Code 128字体实现条码打印
  3. javaScript中常见的几种报错类型
  4. boost::graph模块BC聚类算法程序的实现
  5. 流水调度问题c语言,基于遗传算法的流水车间调度问题汇总.doc
  6. C++(STL):31 ---关联式容器map源码剖析
  7. 微服务集成cas_Spring Boot + Solr 全文检索微服务简易集成
  8. mysql控制台操作
  9. 【3】docker-compose
  10. SpringBoot+JWT整合-解决登陆验证问题
  11. Python爬取12306车次信息
  12. Windows Azure AppFabric (一) 平台简介
  13. TMS320DM642调试出现#10247-D creating output section .capChaACrSpace without a SECTIONS 解决办法...
  14. 文件的三种加载方式(全网讲解最全,最严谨)
  15. 攻防世界Let_god_knows
  16. spark idea报错:json standard allows only one-top level
  17. jira -workflow之父级任务关注人copy到子任务
  18. NMOS的栅极充电过程
  19. Flex在线文档阅读器::pdf、doc、docx、xls、xlsx、ppt、pptx、htm、txt、rtf、epub、csv、xdoc等
  20. redis实现计时器

热门文章

  1. smali语言详解之创建对象
  2. 运算法则(笛卡尔乘积)
  3. php mysql安装图解_mysql安装图解 mysql图文安装教程(详细说明)_MySQL
  4. 12.6pygame游戏开发框架(6):绘制文字
  5. Linux命令之反转文本rev
  6. 疑惑,System.currentTimeMillis真有性能问题?
  7. 关于FFMPEG在Wiindows下使用Movie Filter添加Logo读取文件问题
  8. 【小强推歌】---邓丽君演绎古词专集《淡淡幽情》
  9. Question2Answer添加百度分享按钮
  10. JfreeChart图表