全部学习汇总: GreyZhang/g_unix: some basic learning about unix operating system. (github.com)
前面完成了一个单独命令执行之后,想放弃这个简单shell的实现。后来想想多少还是有几分不甘心,还是耐着心思把这个做完吧!
这次,看一下重定向的相关实现。这部分实现,我是参考了一些其他人的实现来做了一个简单的调试。
这是重定向部分的实现,关键点还是几个文件操作接口的应用。而这几个应用,在之前已经单独做了梳理。
至于这个重定向的处理,首先我们得回顾一下之前看到的重定向的代码实现部分。
在重定向的过程中,原来的命令通过一个cmd的成员进行了封装存放。文件也是继续绑定之前的文件。而这里的flags的处理则是根据究竟是输入还是输出导向进行了一个操作属性的设置。同时,重定向借用的是标准输入以及标准输出两个特殊的文件描述符。这里也根据重定向的属性进行了fd的分配。
由此,当我们回到上面的重定向的case处理分支中的时候,相应的文件描述符的信息就应该有一个清晰的概念了。其实,通过反复的处理这里实现的处理只是巧妙地新创建文件描述符并且关闭之前的文件描述符来做一个概念上的切换。这个概念是如何进行的切换呢?首先,通过新的open操作来对原来的文件进行了对等的flags等操作绑定了新的文件描述符。接着,关闭了原来的文件绑定的文件描述符,而这个绑定其实是标准的输入输出。接下来,通过dup分配了一个全新的文件描述符,这个文件描述符有着跟前面的open对等的一个处理效果。仅仅通过这些信息可能还是有点漏洞,那么这样的漏洞是如何补充起来的呢?那就是这个命令的解析其实是发生在一个全新的子进程中!因此,在这段处理执行之前,其实文件描述符是一个未使用状态。如此,输入会被关联到标准输入输出以及错误之外的文件描述符上,也就是从3开始。但是,dup的行为又较为特殊。只要是没有使用的文件描述符都是可以分配的。因此,如果当前已经在工作的是标准输入,那么文件将会被绑定到标准输出上。而当前工作的假如是标准输出,文件则会被绑定的标准输入上。如此,也就实现了重定向。
关于这部分,我们可以通过增加一个输出打印来看看具体的分析猜测。
代码中增加这样的一个输出,之后测试一下输入输出的重定向。
从上面的结果看,这个还是跟分析的内容一致的。
重定向处理的是相关的文件,而文件处理完之后还需要按照普通的方式进行命令的调用。这也就是最后一个命令调用实现的功能了。
管道命令的实现基本上也是这样的技巧,这里就不去深入分析了。