【Linux】重定向 1、理解重定向在task_struct结构体中存放files_struct*指针指向本进程的文件描述符表fd_array文件描述符的分配规则是从下标0开始找值最小并且没有被使用的位置正常程序默认打开0、1、2这三个位置全部被占用默认起始下标为3如果先执行close(2)那么起始下标就为2#includestdio.h#includesys/types.h#includesys/stat.h#includefcntl.h#includeunistd.h#includestring.hintmain(){close(2);intfdaopen(log.txt,O_WRONLY|O_CREAT|O_TRUNC,0666);printf(fda: %d\n,fda);intfdbopen(log.txt,O_WRONLY|O_CREAT|O_TRUNC,0666);printf(fdb: %d\n,fdb);intfdcopen(log.txt,O_WRONLY|O_CREAT|O_TRUNC,0666);printf(fdc: %d\n,fdc);return0;}1为显示器输出如果把1号下标对应的文件关闭那么将产生输出重定向#includestdio.h#includesys/types.h#includesys/stat.h#includefcntl.h#includeunistd.h#includestring.hintmain(){close(1);intfdaopen(log.txt,O_WRONLY|O_CREAT|O_TRUNC,0666);printf(fda: %d\n,fda);intfdbopen(log.txt,O_WRONLY|O_CREAT|O_TRUNC,0666);printf(fdb: %d\n,fdb);intfdcopen(log.txt,O_WRONLY|O_CREAT|O_TRUNC,0666);printf(fdc: %d\n,fdc);return0;}当运行operfile程序时无输出内容全部写入了log.txt中完成输出重定向文件描述符1这个编号从绑定屏幕改成了绑定log.txtfd[1]中存储的内容指向了log.txt的内容并且操作系统更改1的指向后语言层并不知道stdout封装1后语言层只认数字1所以重定向的本质是更改数组特定下标内的内容2、dup2dup2为系统调用的重定向函数函数定义intdup2(intoldfd,intnewfd);将newfd变成oldfd的副本如果newfd原本打开了资源会先自动关闭newfddup2实现重定向的方式不是先关闭文件描述符再打开一个文件而是将oldfd下标里存储的文件拷贝到newfd中#includestdio.h#includesys/types.h#includesys/stat.h#includefcntl.h#includeunistd.h#includestring.hintmain(){// close(1); 注释掉不手动关闭标准输出fd1intfdaopen(log.txt,O_WRONLY|O_CREAT|O_TRUNC,0666);printf(fda: %d\n,fda);// 输出 3dup2(fda,1);// fd1现在指向log.txt内容写入文件printf(aaaaaa);printf(aaaaaa);printf(aaaaaa);fprintf(stdout,aaaaaa\n);return0;}dup2让fd1复制fda指向的文件实现标准输出重定向把O_TRUNC替换成O_APPEND可以实现追加重定向3、输入重定向使用cat命令时cat会从键盘读取数据但输入重定向后会从log.txt中读取内容#includestdio.h#includesys/types.h#includesys/stat.h#includefcntl.h#includeunistd.h#includestring.hintmain(){intfdopen(log.txt,O_RDONLY);printf(fd: %d\n,fd);dup2(fd,0);// 从标准输入读取数据charbuf[64];fgets(buf,sizeof(buf),stdin);printf(读取到文件内容%s,buf);close(fd);return0;}dup2(fd, 0);把打开的文件fd覆盖掉0号文件描述符之后所有读 stdin 的操作不再读键盘而是读log.txt这就是程序内部实现输入重定向4、理解一切皆文件键盘、显示器、网卡、硬盘等硬件底层读写逻辑完全不相同为什么上层可以统一用同一个接口每次打开一个文件或设备时内核都会创建一个独立的struct file对象内部有函数指针数组操作系统向上层应用提供统一的IO接口通过内核struct file 驱动函数指针把磁盘文件、键盘、显示器、网卡、管道、套接字全部抽象成文件统一管理。所以应用层调用open或write等函数时会通过fd下标找到进程文件描述符表拿到struct file*自动跳转到底层硬件驱动专属方法上层应用完全不用区分硬件类型接口是统一的