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

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

本文章收录于专栏【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. oracle schema与mysql_Oracle数据库之Oracle 11g R2 用户与模式(schema)
  2. 程序员客栈携手野狗 体验国内领先的实时后端云协作
  3. Hibernate映射解析——七种映射关系
  4. ipython notebook主题背景颜色更改
  5. python 基础学习 正则表达式1(规则)
  6. Java通过class文件得到所在jar包
  7. leetcode 222 Count Complete Tree Nodes
  8. node11---相册
  9. vue上传图片文件到服务器,vue如何将quill图片上传到服务器
  10. “红孩儿”成中科院博士!做CTO身价过亿!
  11. macOS Big Sur安装Mojave动态桌面壁纸
  12. MFC API 设置Excel单元格格式
  13. 对比stm32,arm9研究方向
  14. HHTC第十二届程序设计竞赛
  15. php gd图片验证,php笔记之GD库图片创建/简单验证码
  16. ASP.NET是什么?与.NET有什么关系
  17. 计算机读不了硬盘分区,一分钟告诉你硬盘要不要分区,为什么
  18. 《2016ThoughtWorks技术雷达峰会----js爆炸下的技术选型》
  19. Ubuntu的一些软件源
  20. 虚拟机和本机互传文件

热门文章

  1. phpcms v9和discuz X3.1实现同步登陆退出论坛(已实现)
  2. iMobile中加载大数据量的矢量数据性能优化方法有哪些
  3. QQmusic imitations record 第二天
  4. C++ static变量
  5. 极度未知HyperX旋火无线鼠标——黑白双色齐飞的专业电竞游戏鼠标
  6. 拍拍贷魔镜杯风控算法大赛——基于lightgbm
  7. php滑动解锁验证码,给WordPress加评论滑动解锁QapTcha验证
  8. System.currentTimeMillis的性能,真有如此不堪吗?
  9. easyUi easyui-textbox 多行换行失效问题
  10. 【微信小程序】-- 页面事件 - 上拉触底(二十六)