linux系统编程之文件的内核结构file和dup实现重定向

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

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

图片[1]-linux系统编程之文件的内核结构file和dup实现重定向-趣考网

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

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

图片[2]-linux系统编程之文件的内核结构file和dup实现重定向-趣考网

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

图片[3]-linux系统编程之文件的内核结构file和dup实现重定向-趣考网

示例程序:

/*************************************************************************    > File Name: file_share.c    > Author: Simba    > Mail: dameng34@163.com    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST ************************************************************************/#include#include#include#include#include#include#include#include#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\\n\", buf1);    fd2 = open(\"test.txt\", O_RDWR);    if (fd2 == -1)        ERR_EXIT(\"open error\");    read(fd2, buf2, 5);    printf(\"buf2=%s\\n\", buf2);    write(fd2, \"AAAAA\", 5);    memset(buf1, 0, sizeof(buf1));    read(fd1, buf1, 5);    printf(\"buf1=%s\\n\", 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得到的也是更改后的值。

需要C/C++ Linux服务器架构师学习资料私信“资料”(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

图片[4]-linux系统编程之文件的内核结构file和dup实现重定向-趣考网

二、I/O重定向

图片[5]-linux系统编程之文件的内核结构file和dup实现重定向-趣考网

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

/*************************************************************************    > File Name: process_.c    > Author: Simba    > Mail: dameng34@163.com    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST ************************************************************************/#include#include#include#include#include#include#include#include#include#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 函数示例程序如下:

/*************************************************************************    > File Name: file_dup.c    > Author: Simba    > Mail: dameng34@163.com    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST ************************************************************************/#include#include#include#include#include#include#include#include#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\\n\"); // 输出重定向到test2.txt    return 0;}
© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享