翼度科技»论坛 云主机 服务器技术 查看内容

Linux文件系统之重定向的实现原理详解

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
一、再来理解重定向


1.1 输出重定向效果演示


分析
  1. ls
复制代码
指令是显示当前目录下的文件,本质就是将当前目录下所有的文件名以字符串的形式写入到显示器文件。采用输出重定向
  1. >
复制代码
,将原本应该写入显示器文件的内容写入到了
  1. log.txtx
复制代码
文件中。

1.2 重定向的原理

在讲解重定向原理前,我们需要明确文件描述符的分配规则,即从0下标开始,寻找最小的没有使用的数组位置,它的下标就是新打开文件的文件描述符。这里没有使用的意思是该下标里面存的是
  1. NULL
复制代码
,即没有指向任何一个文件对象。下面通过一段代码来为大家展示重定向的原理。
  1. // mytest.c
  2. int main()
  3. {
  4.     close(1);
  5.     int fd = open(FILE_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  6.     if(fd < 0)
  7.     {
  8.         perror("open");
  9.         return errno;
  10.     }

  11.     const char* str = "Hello Linux!\n";
  12.     int cnt = 5;
  13.     while(cnt--)
  14.     {
  15.         write(1, str, strlen(str));
  16.     }
  17.     return 0;
  18. }
复制代码
代码分析:上面这段代码就完美的展示了重定向的原理。首先调用
  1. close
复制代码
系统调用将 1 号下标对应的文件关闭,关闭的意思就是将 1 下标里的内容置为
  1. NULL
复制代码
,原本 1 下标里面存储的内容是显示器文件对象的地址,也就是标准输出
  1. stdout
复制代码
,紧接着调用
  1. open
复制代码
打开了一个文件,根据文件描述符的分配规则,新打开的这个文件的文件描述符就是 1,即文件描述符表(
  1. file*
复制代码
的数组)1 号下标里面存储的就是新打开的文件对象的地址。接下来调用
  1. write
复制代码
接口,向 1 号文件描述符中进行写入,本来 1 号文件描述符对应的是显示器文件,原本向显示器文件中写入的内容,此时就被写入到新打开的文件中,没有向显示器文件中写入,因此屏幕上就不会出现字符串,至此整个重定向的过程就结束啦。

总结:重定向的本质是对数组下标里面的内容进行修改。


1.3 dup2

上面介绍了重定向的原理,下面介绍一下实现重定向的系统调用
  1. dup2
复制代码
  1. #include <unistd.h>int dup2(int oldfd, int newfd);
复制代码
  1. dup2
复制代码
的具体实现并不是向上面代码中那样,先将一个文件描述符关闭,然后紧接着再打开一个文件。
  1. dup2
复制代码
的使用方法是,用户在调用
  1. dup2
复制代码
接口前,正常打开一个文件,不用将显示器文件关闭,此时新打开文件的文件描述符就是 3。接下来调用
  1. dup2
复制代码
,将新打开文件的文件描述符作为
  1. oldfd
复制代码
,将显示器文件的文件描述符也就是 1,作为
  1. newfd
复制代码
。我们知道,文件描述符本质上就是数组下标,
  1. dup2
复制代码
函数中执行的工作就是将
  1. oldfd
复制代码
下标里存储的文件对象地址拷贝到
  1. newfd
复制代码
下标里面,至此重定向工作就完成了。

小Tips
  1. dup2
复制代码
的函数形参有一个误导,我们可能会觉得新打开文件的描述符是
  1. newfd
复制代码
,其实不然,这里的
  1. newfd
复制代码
是将要被覆盖的文件描述符,
  1. oldfd
复制代码
是新打开文件的描述符。
  1. int main()
  2. {
  3.     // close(1);
  4.     int fd = open(FILE_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  5.     if(fd < 0)
  6.     {
  7.         perror("open");
  8.         return errno;
  9.     }
  10.     dup2(fd, 1);
  11.     const char* str = "Hello Linux!\n";
  12.     int cnt = 5;
  13.     while(cnt--)
  14.     {
  15.         write(1, str, strlen(str));
  16.     }
  17.     return 0;
  18. }
复制代码

代码分析:上面就是输出重定向的实现原理,追加重定向只需要把
  1. O_TRUNC
复制代码
替换成
  1. O_APPEND
复制代码


1.4 输入重定向效果演示


分析
  1. cat
复制代码
指令本来是从键盘文件中获取输入然后写入显示器文件中,采用输入重定向
  1. <
复制代码
后,是从
  1. log.txt
复制代码
文件中获取输入然后写入显示器文件中。

1.5 输入重定向代码实现
  1. // 输入重定向int main(){    int fd = open(FILE_PATH, O_RDONLY);    if(fd < 0)    {        perror("open");    }    dup2(fd, 0);    char str[1024];    ssize_t ret = read(fd, str, sizeof(str) - 1);    if(ret > 0)    {        str[ret] = '\0';        printf("echo: %s", str);    }    return 0;}
复制代码

小Tips:进程历史打开的文件与进行的各种重定向关系都和未来进行的程序替换无关,程序替换并不影响文件访问。进程打开文件和何种重定向工作,本质上都是进程管理的模块,而程序替换只会把用户空间的代码和数据完全被新程序替换,不会影响到进程管理。

二、再来理解标准输出和标准错误
  1. int main()
  2. {
  3.     fprintf(stdout, "Standard output messages\n");
  4.     fprintf(stdout, "Standard output messages\n");
  5.     fprintf(stdout, "Standard output messages\n");

  6.     fprintf(stderr, "Standard error messages\n");
  7.     fprintf(stderr, "Standard error messages\n");
  8.     fprintf(stderr, "Standard error messages\n");
  9.     return 0;
  10. }
复制代码

代码分析
  1. >
复制代码
是输出重定向,也就是对标准输出(1号文件描述符)进行重定向。标准错误对应的2号文件描述符并没有进行重定向,因此标准错误消息仍然打印在了屏幕上。

2.1 同时对标准输出和标准错误进行重定向
  1. ./mytest 1>output.txt 2>error.txt
复制代码
小Tips:这段代码就是将1号文件描述符对应的标准输出文件重定向到 output.txt 文件,将2号文件描述符对应的标准错误文件重定向到 error.txt 文件。这样以来屏幕上就不会有任何输出。


2.2 将标准输出和标准错误重定向到同一个文件
  1. ./mytest 1>all.txt 2>&1
复制代码

小Tips:将标准输出和标准错误都重定向到 all.txt 文件中。

三、再看一切皆文件

所有操作计算机的动作,都是通过进程去执行的,所有的访问文件操作,都是通过进程去实现的,目前所有对文件的操作都依赖于进程。

小Tips:所有的外设都被抽象成了文件,每个外设都有自己的读写方法,不同的外设读写方法一定是不同的。但是我们在对文件进行读写操作的时候,始终调用的都是
  1. read
复制代码
  1. write
复制代码
方法,这是因为操作系统为我们提供了一个方法集类型
  1. file_operations
复制代码
,该结构体里面都是函数指针类型,指向外设的各种方法,这就是多态的雏形。所谓的一切皆文件,就是操作系统帮我们封装了一层文件对象,进程对各种外设的操作,全都变成了对文件的操作。
  1. sszie_t read(int fd){        task_struct->files->fd_array[fd]->f_op->read();}
复制代码
四、结语

以上就是Linux文件系统之重定向的实现原理详解的详细内容,更多关于Linux重定向的资料请关注脚本之家其它相关文章!

来源:https://www.jb51.net/server/316014quh.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具