• Linux——文件描述符(fd)与重定向、dup/dup2


    目录

    一.文件描述符

    (一).含义

    (二).使用

    (三).标准输入/输出/错误

    二.重定向与dup/dup2

    (一).dup/dup2 

    (二).重定向 


    一.文件描述符

    (一).含义

    文件描述符(file descriptor)简称为fd,其本质就是一个数组下标

    当创建一个进程时,操作系统不仅会创建task_struct结构体(PCB进程控制块),还会创建一个files_struct结构体用于表示该进程打开的相关文件。进程控制块中有一个指针会指向该files_struct。

     在files_struct结构体内部,有一个结构体指针数组fd_array。fd_array是一个数组,里面存放的是指针,每一个指针都指向一个file结构体。

    文件描述符fd就是fd_array的数组下标。

    (二).使用

    以c语言fwrite函数为例,fwrite内部通过FILE结构体找到文件描述符fd,同时调用系统接口write。

    操作系统根据调用的write的进程,通过task_struct结构体内部指针,找到files_struct,再通过files_struct内的fd_array指针数组,依照write传入的具体fd值(下标),找到对应的file结构体,就找到了相关文件。

    图例如下:

    当进程打开一个文件时,系统就会在fd_array内部从0下标开始依次寻找尚未指向具体file的指针(空指针),将该文件的file结构体给这个指针。 

    关闭一个文件时,fd_array中相关指针会指向空,当再其他文件打开时,按照从0开始寻找空指针的方式,找到该空指针,让其指向新的文件。

    (三).标准输入/输出/错误

    名称硬件FILE*fd
    标准输入键盘stdin0
    标准输出显示器stdout1
    标准错误显示器stderr2

    以C语言为例,头文件内部已经提前打开了三个文件(两个硬件:键盘、显示器)。

    即标准输入、标准输出、标准错误。依照fd_array对文件描述符的分配规则,从0下标开始依次指向具体的file。这也就是为什么标准输入、标准输出、标准错误的fd默认为0、1、2。

    所以,下面代码也就很好理解了:

    1. int main()
    2. {
    3. const char* str = "hello world\n";
    4. fwrite(str, strlen(str), 1, stdout);
    5. return 0;
    6. }

    stdout是头文件定义的表示显示器的FILE指针,指针指向的FILE结构体内部fd值为1,因此fwrite直接通过stdout这个指针获得相关fd,进而使用显示器。

    二.重定向与dup/dup2

    有了对于文件描述符的理解, 重定向的概念就很好理解了。

    (一).dup/dup2 

    这种替换可以通过系统接口dup2完成。

    不管是dup还是dup2因为是系统接口,其参数均是文件描述符fd。 

    dup可以返回一个新的fd来表示传入的oldfd所代表的文件,即赋予该文件另一个fd。

    dup2可以将oldfd所代表的文件给newfd,如果两个fd所代表的文件本就相等,那将不做任何改动。

    dup2在使用时常常容易搞错复制方向,可以这样理解:dup2(copy from, copy to)

     如果调用失败,均返回-1。

    (二).重定向 

    重定向本质是使fd_array中指向原文件的指针指向目标文件。 

     以标准输出重定向为例:

    [cdl@VM-16-9-centos ~]$ echo "hello world" > file.txt

    本质就是将fd_array中原本指向显示器file的指针指向file.txt的file结构体,即:

    1. FILE* file = fopen("./file.txt", ...);
    2. dup2(file._fileno, 1);

    echo还是将数据给fd为1的指针指向的文件,但因为fd=1的指针指向了file.txt(的file结构体),因此echo把数据给了file.txt。 

    图示如下:

    追加重定向就是在打开file.txt文件时就赋予文件追加属性,相当于这样:

    1. //系统open接口,O_TRUNC:按追加方式打开文件
    2. int fd = open("./file.txt", O_CREAT | O_RDWR | O_TRUNC);

    愚者困惑,智者提问——Benjamin Disraeli


    如有错误,敬请斧正

  • 相关阅读:
    SQL每日一练(牛客新题库)——第3天: 条件查询
    Python之作业(二)
    软件过程与建模学习之:Ethics, ACs Code Ethics, IEEE Code of Ethics
    免费享受企业级安全:雷池社区版WAF,高效专业的Web安全的方案
    idea创建的idea项目springframework是红色的
    C/C++字符三角形 2020年12月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析
    SQL Server SSIS ETL job执行相关操作
    数据库基础——4.select语句
    Dubbo3应用开发—Dubbo3注册中心(zookeeper、nacos、consul)的使用
    深挖全媒体多模态数据价值,蜜度亮相2022世界人工智能大会
  • 原文地址:https://blog.csdn.net/weixin_61857742/article/details/127835592