dup2 错误的文件描述符错误
Posted
技术标签:
【中文标题】dup2 错误的文件描述符错误【英文标题】:dup2 bad file descriptor error 【发布时间】:2011-12-08 09:29:45 【问题描述】:我正在尝试使用从website 获得的教程来实现多个管道。在执行处理多个管道的函数后,我似乎遇到了错误的文件描述符错误。当我第一次欺骗时,它会向我发送此错误。代码如下:
void runPipedCommands(cmdLine* command, char* userInput)
int numPipes = countPipes(userInput);
int status = 0;
int i = 0, j = 0;
pid_t pid;
int pipefds[2*numPipes];
for(i = 0; i < (numPipes); i++)
if(pipe(pipefds + i*2) < 0)
perror("pipe");
exit(EXIT_FAILURE);
j = 0;
while(command)
pid = fork();
if(pid == 0)
//if not first command
if(j != 0)
if(dup2(pipefds[j-2], 0) < 0)
perror(" dup2");///j-2 0 j+1 1
exit(EXIT_FAILURE);
if(command->next)
printf(
if(dup2(pipefds[j + 1], 1) < 0)
perror("dup2");
exit(EXIT_FAILURE);
for(i = 0; i < 2*numPipes; i++)
close(pipefds[i]);
if( execvp(*command->arguments, command->arguments) < 0 )
perror(*command->arguments);
exit(EXIT_FAILURE);
else if(pid < 0)
perror("error");
exit(EXIT_FAILURE);
command = command->next;
j++;
for(i = 0; i < 2 * numPipes; i++)
close(pipefds[i]);
printf("in parent: closed pipe[%d]\n", i);
wait(0);
也许某处有泄漏,或者找不到描述符。我似乎不知道问题出在哪里。我做错了什么?谢谢。
修改后的代码:
void runPipedCommands(cmdLine* command, char* userInput)
int numPipes = countPipes(userInput);
int status = 0;
int i = 0, j = 0;
pid_t pid;
int pipefds[2*numPipes];
for(i = 0; i < (numPipes); i++)
if(pipe(pipefds + i*2) < 0)
perror("pipe");
exit(EXIT_FAILURE);
j = 0;
while(command)
pid = fork();
if(pid == 0)
//if not first command
if(j != 0 && j!= 2*numPipes)
if(dup2(pipefds[j-2], 0) < 0)
perror(" dup2");///j-2 0 j+1 1
exit(EXIT_FAILURE);
//if not last command
if(command->next)
printf("command exists: dup(pipefd[%d], 1])\n", j+1);
if(dup2(pipefds[j + 1], 1) < 0)
perror("dup2");
exit(EXIT_FAILURE);
for(i = 0; i < 2*numPipes; i++)
close(pipefds[i]);
printf("in child: closed pipe[%d]\n", i);
if( execvp(*command->arguments, command->arguments) < 0 )
perror(*command->arguments);
exit(EXIT_FAILURE);
else if(pid < 0)
perror("error");
exit(EXIT_FAILURE);
command = command->next;
j+=2;
for(i = 0; i < 2 * numPipes; i++)
close(pipefds[i]);
printf("in parent: closed pipe[%d]\n", i);
wait(0);
【问题讨论】:
你得到什么错误?在哪里? @sarnold:我在dup2(pipefds[j-2], 0)
收到dup2: bad file descriptor
。
这是相当混乱的代码;我试了一下,但您最好通过strace(1)
、ltrace(1)
或gdb(1)
运行它,并观察它们的每一步。
【参考方案1】:
好的,首先,有点奇怪 - 您的嵌套与您的大括号不对齐。 if (j != 0)
和 if(command->next)
看起来像同一个“级别”,但实际的大括号讲述的是不同的故事:
复制粘贴:
if(j != 0)
if(dup2(pipefds[j-2], 0) < 0)
perror(" dup2");///j-2 0 j+1 1
exit(EXIT_FAILURE);
if(command->next)
printf(
if(dup2(pipefds[j + 1], 1) < 0)
perror("dup2");
exit(EXIT_FAILURE);
重新缩进以反映大括号:
if (j != 0)
if (dup2(pipefds[j - 2], 0) < 0)
perror(" dup2"); ///j-2 0 j+1 1
exit(EXIT_FAILURE);
if (command->next)
printf(); /* fixed this */
if (dup2(pipefds[j + 1], 1) < 0)
perror("dup2");
exit(EXIT_FAILURE);
请让您的 IDE、编辑器或 indent(1)
重新缩进您的代码以反映代码的实际语法,以免您被误导性的空格弄糊涂。
其次,我认为您在较早的迭代中将 j+=2
从 j++
更改了,但并没有完全这样做——在第一次通话中,您使用的是 pipefds[j-2]
,而在下一次通话中,您将使用“重新使用pipefds[j+1]
。在第一次迭代中j-1
发生了什么?它被忽略。这是故意的吗? j
仅在 next 迭代中被引用(通过 j+=2 .. [j-2]
)。任何东西都会引用pipefds[]
中的倒数第二个条目吗?这也是故意的吗?
【讨论】:
天哪。谢谢。我没有注意到这一点。是的,我的牙套嵌套不好。现在纠正他们。其次,是的,我确实从早期代码中更改了j+=2
from a j++
。我已经改回来了。实际上我使用j
来检查当前命令是否不是第一个命令。如果不是我重复,否则我不会。所以这解决了坏文件描述符的问题。 Will anything ever reference the next-to-last entry in pipefds[]
是什么意思?
哦。你的意思是我如何检查它是否是堆栈上的最后一个命令?是的,我需要检查一下。这不是故意的。我没想到...粗心的我。 if(j != 0 && j!= numPipes -1)
会吗?
对于next-to-last entry in pipefds[]
,它只是注意到你有一个“滑动窗口”,适用于j-2
、j+1
,并将j
增加@987654343 @(并跳过第一个 j==0
)。这将 选择 [ 0, 1, 2, 3, 4, 5, 6, 7 ] 当numPipes==4
. (在一张纸上为j-2
和j+1
剪洞,然后沿着文本滑动。)也许这是故意的,也许不是,但我已经没有足够的脑力来确定了。 :)
这不是故意的。实际上我不再使用j+=2
。我现在使用j++
。当我使用j+2
时,我调用了dup2(pipefds[(j-1) * 2])
和dup2(pipefds[j * 2 + 1], 1)
。那时就是这样。但现在我将坚持使用j++
并使用j-2
、j+1
。哦,请不要现在用尽脑力:)。我还需要一些帮助。纠正一切后,管道无法正常工作。当我输入ls | grep bin
之类的内容时,找不到任何结果。当我想输入另一个命令时,它会挂起。
等等,我在上面写了废话。目前,在更改代码后,我使用j+=2
递增并调用(dup2(pipefds[j-2], 0)
和(dup2(pipefds[j+1], 1)
。【参考方案2】:
这是问题的答案。希望它可以帮助那里的人。我最终决定将 j
增加 2 (j+=2)
。函数countPipes(char*)
只是一个简单的函数,用于从char*
中计算管道(|)
的数量
void runPipedCommands(cmdLine* command, char* userInput)
int numPipes = countPipes(userInput);
int status;
int i = 0;
pid_t pid;
int pipefds[2*numPipes];//declare pipes
/**Set up pipes*/
for(i = 0; i < (numPipes); i++)
if(pipe(pipefds + i*2) < 0)
perror("couldn't pipe");
exit(EXIT_FAILURE);
int j = 0;
while(command)
pid = fork();
if(pid == 0)
//if not last command
if(command->next)
if(dup2(pipefds[j + 1], 1) < 0)
perror("dup2");
exit(EXIT_FAILURE);
//if not first command
if(j != 0 )
if(dup2(pipefds[j-2], 0) < 0)
perror(" dup2");///j-2 0 j+1 1
exit(EXIT_FAILURE);
//close pipes in child
for(i = 0; i < 2*numPipes; i++)
close(pipefds[i]);
//execute commands
if( execvp(*command->arguments, command->arguments) < 0 )
perror(*command->arguments);
exit(EXIT_FAILURE);
else if(pid < 0)
perror("error");
exit(EXIT_FAILURE);
command = command->next;//go to the next command in the linked list
j+=2;//increment j
/**Parent closes the pipes and waits for all of its children*/
for(i = 0; i < 2 * numPipes; i++)
close(pipefds[i]);
for(i = 0; i < numPipes + 1; i++) //parent waits for all of its children
wait(&status);
【讨论】:
以上是关于dup2 错误的文件描述符错误的主要内容,如果未能解决你的问题,请参考以下文章