重定向后,打开的文件描述符太多了。让我们剖析两段:
if (in) { //if '<' char was found in string inputted by user fd = open(input, O_RDONLY, 0); dup2(fd, STDIN_FILENO); in = 0; current_in = dup(0); // Fix for symmetry with second paragraph}if (out) { //if '>' was found in string inputted by user fd = creat(output, 0644); dup2(fd, STDOUT_FILENO); out = 0; current_out = dup(1);}我将慈善起来,忽略您忽略错误的事实。但是,您将需要错误检查系统调用。
在第一段中,打开文件并在变量中捕获文件描述符(很可能是3)
fd。然后,您可以在标准输入(
STDIN_FILENO)上复制文件描述符。但是请注意,文件描述符3仍处于打开状态。然后,执行一个
dup(0)(为了保持一致,应该为
STDIN_FILENO),得到另一个文件描述符,也许是4。因此,文件描述符0、3和4指向相同的文件(实际上是相同的打开文件描述,请注意)打开文件描述与打开文件描述符不同)。如果您打算
current_in保留(父)外壳的标准输入,则必须先执行此操作,
dup()然后再执行
dup2()覆盖输出。但是,最好不要更改父Shell的文件描述符。它比重新复制文件描述符要少。
然后,您或多或少重复第二段中的过程,首先覆盖通过
fd =creat(...)调用打开的文件描述符3的唯一记录,但获得一个新的描述符(可能是5),然后在标准输出中复制该描述符。然后执行
dup(1),产生另一个文件描述符,也许是6。
因此,您已经将主外壳程序的stdin和stdout重定向到了文件(并且没有将它们恢复为原始值的方法)。因此,您的第一个问题是您要先进行重定向
fork();您应该在之后执行该操作
fork()-尽管在流程之间进行管道传输时,需要在创建分支之前创建管道。
第二个问题是,您需要关闭过多的文件描述符,而其中的一个文件描述符将不再具有引用。
因此,您可能需要:
if ((pid = fork()) < 0) ...error...else if (pid == 0){ if (in) { int fd0 = open(input, O_RDONLY); dup2(fd0, STDIN_FILENO); close(fd0); } if (out) { int fd1 = creat(output , 0644) ; dup2(fd1, STDOUT_FILENO); close(fd1); } ...now the child has stdin coming from the input file, ...stdout going to the output file, and no extra files open. ...it is safe to execute the command to be executed. execve(cmd[0], cmd, env); // Or your preferred alternative fprintf(stderr, "Failed to exec %sn", cmd[0]); exit(1);}else{ ...wait for child to die, etc...}在执行任何此操作之前,您应该确保已使用刷新了Shell的标准I /
O通道
fflush(0),这样,如果派生的子级由于问题而写入标准错误,则不会有多余的重复输出。
还要注意,
open()应该对各种调用进行错误检查。



