• 文件的内核结构file和dup实现重定向


    一、打开文件内核数据结构

    1、一个进程打开两个文件


    文件状态标志:读、写、追加、同步、非阻塞等


    2、一个进程两次打开同一文件


    3、两个进程打开同一文件


    示例程序:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    /*************************************************************************
        > File Name: file_share.c
        > Author: Simba
        > Mail: dameng34@163.com
        > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
     ************************************************************************/
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<unistd.h>
    #include<fcntl.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<errno.h>
    #include<string.h>

    #define ERR_EXIT(m) 
        do { 
            perror(m); 
            exit(EXIT_FAILURE); 
        } while(0)

    int main(int argc, char *argv[])
    {
        int fd1, fd2;
        char buf1[1024] = {0};
        char buf2[1024] = {0};
        /* 进程控制块PCB
         * struct task {
         * ...
         * struct files_struct *files;
         * }
         * 同一个进程两次打开同一个文件,一个进程拥有的一个文件描述符表其中一个fd索引对应的指针指向一个
         * 文件表(包括文件状态(读写追加同步非阻塞等),当前文件偏移量,
         * 文件引用次数(当有两个fd指向同个文件表时引用计数为2,见dup,也可用于重定向),
         * 文件操作指针, V节点指针等)不共享,
         * V节点表(包括V节点信息(struct stat), i节点信息等)共享
         */
        /* 两个进程打开同一个文件的情况与上类同*/
        fd1 = open("test.txt", O_RDONLY);
        if (fd1 == -1)
            ERR_EXIT("open error");
        read(fd1, buf1, 5);
        printf("buf1=%s ", buf1);


        fd2 = open("test.txt", O_RDWR);
        if (fd2 == -1)
            ERR_EXIT("open error");
        read(fd2, buf2, 5);
        printf("buf2=%s ", buf2);
        write(fd2, "AAAAA", 5);

        memset(buf1, 0, sizeof(buf1));
        read(fd1, buf1, 5);
        printf("buf1=%s ", buf1);
        close(fd1);
        close(fd2);

        return 0;
    }


    假设test.txt文件的内容是 ABCDEhello

    测试如下:

    simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_share 
    buf1=ABCDE
    buf2=ABCDE
    buf1=AAAAA

    test.txt文件内容变成 ABCDEAAAAA

    分析:由上图分析可知,一个进程两次打开同一文件,文件表是不共享的,即各有自己的文件偏移量和打开文件标志,所以两次read不同的fd都是从头开始读取,但V节点表是共享的,在fd2写入(同个文件表的read和write是共享偏移的)更改了inode指向的硬盘数据块,再次read fd1得到的也是更改后的值。


    二、I/O重定向



    当我们执行了dup(3)之后,系统选择一个空闲的文件描述符即4,这样就有两个文件描述符指向同个文件表,所以引用计数为2。利用dup等函数可以进行重定向的步骤是先close输入输出文件描述符,然后执行dup(fd), 这样输入输出文件描述符也指向fd指向的文件,这样就实现了重定向。此外dup2, fcntl 函数也可以实现,其实不使用这些函数,而直接close(0/1/2)完再open也可以实现。如下使用cat命令实现复制文件的功能:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    /*************************************************************************
        > File Name: process_.c
        > Author: Simba
        > Mail: dameng34@163.com
        > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
     ************************************************************************/
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<unistd.h>
    #include<fcntl.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<errno.h>
    #include<string.h>
    #include<signal.h>
    #define ERR_EXIT(m) 
        do { 
            perror(m); 
            exit(EXIT_FAILURE); 
        } while(0)

    int main(int argc, char *argv[])
    {
        close(0);
        open("Makefile", O_RDONLY);
        close(1);
        open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664);

        execlp("cat", "cat", NULL);

        return 0;
    }

    现在标准输入是文件Makefile,标准输出是文件test.txt ,将当前进程替换成cat,则cat会从标准输入读而后输出到标准输出,即完成了copy的功能。


    dup/fcntl 函数示例程序如下:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    /*************************************************************************
        > File Name: file_dup.c
        > Author: Simba
        > Mail: dameng34@163.com
        > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
     ************************************************************************/
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<unistd.h>
    #include<fcntl.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<errno.h>
    #include<string.h>

    #define ERR_EXIT(m) 
        do { 
            perror(m); 
            exit(EXIT_FAILURE); 
        } while(0)

    /* dup dup2 fcntl */
    int main(int argc, char *argv[])
    {
        int fd;
        fd = open("test2.txt", O_WRONLY);
        if (fd == -1)
            ERR_EXIT("open error");
        /*
            close(1);
            dup(fd);
        */
        //  dup2(fd, 1);

        close(1);
        if (fcntl(fd, F_DUPFD, 0) < 0) //从0开始搜索可用的fd
            ERR_EXIT("fcntl error");
        printf("hello "); // 输出重定向到test2.txt
        return 0;
    }


    参考:《APUE》

  • 相关阅读:
    flowable的多人会签和一票否决
    排序
    Java数组的三种打印方式
    CF446B DZY Loves Modification(优先队列)
    2019CCPC哈尔滨 Interesting Permutation(思维)
    2019沈阳网络赛 Fish eating fruit (换根dp)
    AcWing287 积蓄程度(换根dp)
    CF1358E Are You Fired?(前缀和+贪心)
    android android studio error
    cocos2D-X 打包
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8477165.html
Copyright © 2020-2023  润新知