【Linux探索学习】第二十一弹——文件描述符和输出重定向:深入解析Linux操 ...

打印 上一主题 下一主题

主题 789|帖子 789|积分 2369

Linux学习笔记:
https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482
前言:
   在上一篇,我们已经讲解过文件描述符的相关问题了,但是今天,由于讲解重定向问题需要更进一步明白文件描述符的问题,以是我们先对文件描述符的问题进行一些增补讲解,然后再重点讲解一下重定向的问题。
  目次

一、文件描述符
1.1 文件描述符的类型
1.2 文件描述符的管理
1.3 文件描述符的相关操纵
二、输出重定向
2.1 根本的重定向
2.2 重定向标准错误输出
2.3 同时重定向标准输出和标准错误输出
2.4 输入输出重定向与管道
三、文件描述符和输出重定向的结合
3.1 重定向的本质
3.2 dup2体系调用来实现重定向
3.3 其它
四、总结


一、文件描述符

我们照旧先再来讲解一遍文件描述符:在Linux中,每个打开的文件都会被分配一个文件描述符。文件描述符是一个非负整数,操纵体系内核通过它来跟踪进程与文件之间的关联。文件描述符提供了与文件进行交互的通道,可以通过它执行各种文件操纵。
1.1 文件描述符的类型

在Linux中,文件描述符被分别为三大类:
   

  • 标准输入(stdin):文件描述符为0,表示步伐的标准输入流,通常指向键盘输入。
  • 标准输出(stdout):文件描述符为1,表示步伐的标准输出流,通常指向终端。
  • 标准错误(stderr):文件描述符为2,表示步伐的标准错误流,也指向终端,通常用于输出错误信息。
  除了这三个标准流,Linux允许通过体系调用打开其他文件或设备,从而获得新的文件描述符。这些文件描述符可以通过文件I/O操纵进行读写。
1.2 文件描述符的管理

文件描述符是由操纵体系内核管理的,它们与一个实际的文件表项(文件描述符表)相对应。每个进程都有一个与之关联的文件描述符表,用于记载当前进程打开的全部文件和设备的信息。
同时每个文件描述符也对应着一个描述该文件的内容及属性的结构体对象,这就是操纵体系管理文件的本质

文件描述符类型描述0stdin标准输入流1stdout标准输出流2stderr标准错误流3+普通文件可通过体系调用open()获取的文件描述符 通过调用open()体系调用,我们可以打开一个文件并获取其对应的文件描述符。open()函数的根本原型如下:
  1. int open(const char *pathname, int flags, mode_t mode);
复制代码
  

  • pathname:文件路径。
  • flags:打开文件时的标志,比方O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写)等。
  • mode:文件权限,仅在创建文件时使用。
  打开文件后,操纵体系会返回一个文件描述符,用于后续的文件操纵。
1.3 文件描述符的相关操纵

在Linux中,文件描述符常用的操纵包罗:
   

  • 读取文件:通过read()体系调用读取文件内容。
  • 写入文件:通过write()体系调用将数据写入文件。
  • 关闭文件:通过close()体系调用关闭文件描述符。
  这些体系调用接口我们在上一篇做过具体讲解了,这里就不再介绍了
二、输出重定向

   输出重定向是将命令的标准输出(stdout)大概标准错误输出(stderr)重定向到文件、设备或其他进程的一个过程。Linux 提供了非常灵活的方式来实现输出重定向。首先我们先来看根本的重定向,也就是在命令行中可以直接实现的重定向
  2.1 根本的重定向

在 Linux 中,我们可以使用 > 或 >> 来将输出重定向到文件。
   

  • >:将输出重定向到文件,如果文件已存在则覆盖。
  • >>:将输出重定向到文件,如果文件已存在则追加。
  比方,执行以下命令时:
  1. echo "Hello, World!" > output.txt
复制代码
这将把字符串 "Hello, World!" 写入到 output.txt 文件中。如果文件已存在,内容将被覆盖。如果文件还没被创建,则会自动创建并写入

2.2 重定向标准错误输出

除了标准输出,还可以将标准错误输出(stderr)重定向到文件:
  1. echo "An error occurred" 2> error.txt
复制代码
这将把标准错误输出写入到 error.txt 文件。
2.3 同时重定向标准输出和标准错误输出

有时,我们盼望将标准输出和标准错误输出都重定向到同一个文件:
  1. echo "This is normal" > output.txt echo "This is an error" 2>> output.txt
复制代码
上面的命令中,标准输出被重定向到 output.txt 文件中,而标准错误输出则追加到文件末端。

2.4 输入输出重定向与管道

重定向不仅仅用于输出,还可以用于输入。比方,我们可以使用 < 来将文件内容作为输入:
  1. cat < input.txt
复制代码
而管道(|)则可以将一个命令的输出作为另一个命令的输入:
  1. ls | grep "example"
复制代码
这将列出当前目次下全部文件,并通过管道将输出传递给 grep,过滤出包含 "example" 的文件名。
三、文件描述符和输出重定向的结合

上面我们所讲的输出重定向还都是最根本的输出重定向,是直接在命令行上就能实现的,下面我们来几个文件描述符的在输出重定向中的高级用法
3.1 重定向的本质

首先我们可以结合文件描述符来讲解一下输出重定向在底层中是如何进行的
首先我们先来看这样一段代码:
  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<sys/types.h>
  4. #include<sys/stat.h>
  5. #include<fcntl.h>
  6. #include<string.h>
  7. #define filename "log.txt"
  8. int main()                                                                                                                                                                                                   
  9. {
  10.     close(1);
  11.     int fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);
  12.     if(fd<0)    //因为文件描述符是数组的下标,所以不可能小于0,小于0就是失败
  13.     {
  14.         perror("open file");
  15.         return 1;
  16.     }
  17.     printf("fd: %d\n",fd);
  18.     const char *msg="hello Linux\n";
  19.     int cnt=5;
  20.     while(cnt)
  21.     {
  22.         write(1,msg,strlen(msg));
  23.         cnt--;
  24.     }
  25.     close(fd);
  26.     return 0
  27. }
  28.    
复制代码
运行效果:

   我们将第一行的解开释开,也就是说关闭1号文件再次执行:
  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<sys/types.h>
  4. #include<sys/stat.h>
  5. #include<fcntl.h>
  6. #include<string.h>
  7. #define filename "log.txt"
  8. int main()                                                                                                                                                                                                   
  9. {
  10.     close(1);
  11.     int fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);
  12.     if(fd<0)    //因为文件描述符是数组的下标,所以不可能小于0,小于0就是失败
  13.     {
  14.         perror("open file");
  15.         return 1;
  16.     }
  17.     printf("fd: %d\n",fd);
  18.     const char *msg="hello Linux\n";
  19.     int cnt=5;
  20.     while(cnt)
  21.     {
  22.         write(1,msg,strlen(msg));
  23.         cnt--;
  24.     }
  25.     close(fd);
  26.     return 0
  27. }
复制代码
运行效果:

   我们比较一下上面的两段代码和输出效果:
  

   我们可以观察到上面这两段代码唯一的区别就是一个事先把1号文件关闭了,但是它们的输出效果却有很大差别,我们的代码执行的目的就是在屏幕上打印log.txt文件的描述符,并把预期内容写入一号文件中去,而前三号文件我们在前面也讲过是我们在启动进程时是会默认创建的文件,1号文件就是显示器文件,以是第一段代码的打印效果就是直接在屏幕上输出全部打印内容,log.txt的文件标识符则为3(0,1,2被占用),而在第二段代码中,我们首先先将1号文件关闭掉,此时数组中1号文件的对应位置就是空了,此时我们在创建log.txt文件时按从小往大的次序,就会先找到1号文件,因为1号显示器文件已经被关闭,以是往屏幕上输出内容的操纵不能见效了,而且内容也被写入在log.txt中
  

   以是说重定向的原理就是文件描述符指向的内容的修改(个人明白)
  3.2 dup2体系调用来实现重定向

首先我们先来通过man手册来看一下dup2的根本用法
  1. man dup
复制代码

我们可以看到关于dup的体系调用接口有两个,我们需要掌握的重要是第二个
   我们上面的那种重定向的方法使用起来是比较繁琐的,我们必须先关闭1号文件,然后再打开新文件时才能乐成,其实也可以通过dup2体系调用的方法直接实现上面的效果
  来看看上面同样的代码我们如何用dup2来实现:
  1. #include<stdio.h>
  2. #include<unistd.h>
  3. #include<sys/types.h>
  4. #include<sys/stat.h>
  5. #include<fcntl.h>
  6. #include<string.h>
  7. #define filename "log.txt"
  8. int main()                                                                                                                                                                                                   
  9. {
  10.     int fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);
  11.     if(fd<0)    //因为文件描述符是数组的下标,所以不可能小于0,小于0就是失败
  12.     {
  13.         perror("open file");
  14.         return 1;
  15.     }
  16.     //重定向
  17.     dup2(fd,1);
  18.     printf("fd: %d\n",fd);
  19.     const char *msg="hello Linux\n";
  20.     int cnt=5;
  21.     while(cnt)
  22.     {
  23.         write(1,msg,strlen(msg));
  24.         cnt--;
  25.     }
  26.     close(fd);
  27.     return 0
  28. }
复制代码
运行效果:

3.3 其它

   上面我们就讲解了输出重定向的重要使用方式,除此之外,输出重定向还可以用在几个更高级的场景,比如背景运行与输出重定向和输出重定向和多重文件描述符等,这些内容都属于拔高内容了,等我们学到后面用到的时间再讲
  四、总结

   文件描述符和输出重定向是 Linux 操纵体系中两个非常重要的机制,它们在体系 I/O 操纵、进程管理和文件体系中饰演着至关重要的角色。通过深入明白文件描述符的底层实现、相关的体系调用以及输出重定向的工作原理,我们可以更高效地与操纵体系交互,了解进程之间交互的本质。
  
  本文具体介绍了文件描述符和输出重定向的基础知识、底层实现、体系调用以及它们在 Linux 中的应用场景。盼望这些知识对你有所帮助。
  本篇笔记:


   感谢各位大佬观看,创作不易,还请各位大佬点赞支持!!!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

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

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

拉不拉稀肚拉稀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表