网站建设中 windows,校园网站建设的用处,网页制作与设计属于什么专业,如何把自己电脑做网站服务器吗文章目录 一、什么是重定向输出重定向的原理认识一下输出重定向的系统调用输出重定向的另外写法 二、浅谈输入重定向三、重定向和进程替换有冲突吗四、Linux下一切皆文件总结 一、什么是重定向
理解重定向之前#xff1a;先理解一个叫做文件描述符的具体操作。
文件描述符先理解一个叫做文件描述符的具体操作。
文件描述符也是在上篇文章提到的 在描述进程属性的PCB对象中存在着一个struct file*的指针该指针指向一个指针数组指针数组的每一个指针又指向对应的文件。
这个文件描述符就是该指针数组的下标
Linux的内核是这样实现的
打开一个文件时会在指针数组中找最近的一个空位置存储该文件的地址。返回的文件描述符就是这个位置的下标。 先看下面的例子 8 #define filename log.txt9 int main()10 {11 int fd open(filename, O_CREAT|O_WRONLY|O_TRUNC, 0666);12 13 if(fd 0)14 {15 perror(open fail);16 return 1;17 }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 printf(%d\n,fd);26 } 从上面的代码不难看出这里是打开一个log.txt的文件并循环打印hello linux到显示器中。 运行结果也是在我们意料之中的。
当我在开头加上
在main函数内的第一行加上:
close(1);这段代码时 会看到两个现象 1.由于已经把1号文件即标准输出流关闭了所以fd文件描述符没有在屏幕上打印是可以理解的。 2.在重新运行该程序前我已经把log.txt文件删除运行程序后重新出现了log.txt文件并且在该文件中出现了本来应该打印在显示器文件的内容 而这个现象就是所谓的输出重定向
输出重定向的原理
原理很简单
在执行了close(1)后1下标的文件描述符对应的指针就被置空了同时维护stdout的引用计数也减减了此时1号下标就是空的
而在此之后创建的新文件会先从指针数组中查找最近的第一个空位置并重新将该位置的指针指向新的文件返回该下标 也就是说新打开的文件占用的是1号下标返回的文件描述符是1
这就解释了为什么本应该向显示器打印的内容打印到了log.txt文件中因为是该log.txt文件占用了1号下标的空间
总结所谓的输出重定向就是将原来的文件向对应的文件数组中对象的地址做一次地址的拷贝
认识一下输出重定向的系统调用 把oldfd拷贝到newfd中最终两个文件fd都是oldfd。
举个简单的例子
假设1号文件描述符存储的是text.txt file*
dup2(3,1);就是将3号这个文件描述符拷贝到1号文件中覆盖拷贝完成后1位置下标和3位置下标对应的文件描述符都是3。
最终两个文件描述符都是3。
输出重定向的另外写法
假设test.c文件有如下内容
int main()
{fprintf(stdout,hello stdout\n); fprintf(stdout,hello stdout\n); fprintf(stdout,hello stdout\n); fprintf(stdout,hello stdout\n); fprintf(stderr,hello stderror\n); fprintf(stderr,hello stderror\n); fprintf(stderr,hello stderror\n); fprintf(stderr,hello stderror\n); return 0;
}编译test.c文件生成test文件后。
执行如下命令
./test 1log.txt 21该代码的意思是 ./test可执行程序本应该向1号文件描述符对应的文件即显示器文件中打印内容的可是被重定向到了log.txt文件中也就是log.txt文件对应文件描述符的内容拷贝到了1号文件的下标中。 所以./test 运行起来的四条printf语句会打印到log.txt文件中。
而21的意思是将1号文件描述符中的指针内容拷贝给2好文件描述符中本来2号文件描述符也是指向显示器文件的至此也同样指向了log.txt文件。
所以log.txt文件会同时出现stdout和stderror两份打印内容。
./test log.txt 21上面的命令还能这样写。也就是把1省略。因为默认就是打印到stdout上的。
二、浅谈输入重定向
输入重定向与输出重定向相反默认从某一个文件中读取。
最简单的例子是
cat log.txt从log.txt文件中读取到stdout显示器文件中。
三、重定向和进程替换有冲突吗
进程替换的本质只是将进程在物理内存中的代码和数据提换成磁盘文件中特定可执行程序的代码和数据。
替换前后并未创建新的进程且替换后只是修改了一下页表的映射关系修改一下进程的虚拟地址空间中的几个参数值。
而重定向的本质是对文件描述符表中的指针进行拷贝修改的文件描述符表的内容与进程替换没有任何关系。
两者各司其职产生了解耦关系。
未来该找进程的文件描述符表中的某一个下标文件写入时就写入内存管理想向特定文件写入就写入与文件描述符表的管理没有任何关系。 四、Linux下一切皆文件
我们平时按的键盘看的显示器网卡声卡磁盘等等这些在Linux下都是文件也就是我们平时所说的外设。
这些外设也是文件。 所以也有文件所有的读方法写方法其他的文件属性等等。
当我们想从键盘中输入一些东西时首先要打开键盘文件。
打开前操作系统会做好一系列准备工作。
创建进程的PCB结构体对象task_struct该结构体对象中能找到管理文件的文件结构对象(files_struct)。
同事这些外设本来就提供有属于它们独有的访问文件的读写方法等。
并且每一个文件在被打开时都会创建属于自己的文件对象struct file这个文件对象中保存该文件的各种属性信息其中就有两个函数指针分别是读指针和写指针指向该文件的读写方法。
在文件结构对象表files_struct中有一个文件描述符数组该数组存储的是各个文件的文件描述符。
通过这些文件描述符即可找到对应的每一个被打开的文件。
而这一系列准备工作完成后假设进程开始调度键盘文件。 该进程就是read系统调用。 read这个进程被运行起来其内部有这样一条核心代码
ssize_t read(int fd)
{task_struct-files_struct-fd_arr[fd]-f_opes-write();
}
首先进程去到自己的task_structPCB对象中找到文件对象表在该表中获取到文件描述符通过文件描述符找到了对应的文件对象再通过文件对象中的一个指针找到描述对应文件的读写方法结构体然后通过该结构体内的读写方法指针获取到对应的读写方法再由该方法调用到对应的外设 所以这就是我们之前经常所说的Linux下一切皆文件的原因
这整个过程就非常像C中的多态
所以可以肯定的是C的多态是抄C语言内核的必定是这样
任何一门语言要支持面向对象它的底层一定会支持这样的思想结构。 总结
Linux下一切皆文件的本质就是面向对象的过程对每个对象分层串联起来就能实现调用不同的外设就能实现不同的功能