C dup2错误的文件描述符错误
我正在尝试使用从本教程中获得的教程来实现多个管道。在执行处理多个管道的函数后,我似乎遇到了一个错误的文件描述符错误。当我第一次复制时,它会向我发送此错误。代码如下:C dup2错误的文件描述符错误,c,linux,shell,pipe,dup2,C,Linux,Shell,Pipe,Dup2,我正在尝试使用从本教程中获得的教程来实现多个管道。在执行处理多个管道的函数后,我似乎遇到了一个错误的文件描述符错误。当我第一次复制时,它会向我发送此错误。代码如下: void runPipedCommands(cmdLine* command, char* userInput) { int numPipes = countPipes(userInput); int status = 0; int i = 0, j = 0; pid_t pid; in
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*命令,char*用户输入){
int numPipes=countPipes(用户输入);
int status=0;
int i=0,j=0;
pid_t pid;
内部管道[2*numPipes];
对于(i=0;i<(numPipes);i++){
如果(管道(管道FDS+i*2)<0){
佩罗(“管道”);
退出(退出失败);
}
}
j=0;
while(命令){
pid=fork();
如果(pid==0){
//如果不是第一个命令
如果(j!=0){
if(dup2(pipefds[j-2],0)<0){
perror(“dup2”);///j-20j+11
退出(退出失败);
}
如果(命令->下一步){
printf(
if(dup2(pipefds[j+1],1)<0){
perror(“dup2”);
退出(退出失败);
}
}
对于(i=0;i<2*numPipes;i++){
关闭(管道[i]);
}
if(execvp(*命令->参数,命令->参数)<0){
perror(*命令->参数);
退出(退出失败);
}
}否则如果(pid<0){
佩罗(“错误”);
退出(退出失败);
}
命令=命令->下一步;
j++;
}
对于(i=0;i<2*numPipes;i++){
关闭(管道[i]);
printf(“在父级中:封闭管道[%d]\n”,i);
}
等待(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);
}
void runPipedCommands(cmdLine*命令,char*用户输入){
int numPipes=countPipes(用户输入);
int status=0;
int i=0,j=0;
pid_t pid;
内部管道[2*numPipes];
对于(i=0;i<(numPipes);i++){
如果(管道(管道FDS+i*2)<0){
佩罗(“管道”);
退出(退出失败);
}
}
j=0;
while(命令){
pid=fork();
如果(pid==0){
//如果不是第一个命令
如果(j!=0&&j!=2*numPipes){
if(dup2(pipefds[j-2],0)<0){
perror(“dup2”);///j-20j+11
退出(退出失败);
}
}
//如果不是最后一个命令
如果(命令->下一步){
printf(“命令存在:dup(pipefd[%d],1])\n”,j+1);
if(dup2(pipefds[j+1],1)<0){
perror(“dup2”);
退出(退出失败);
}
}
对于(i=0;i<2*numPipes;i++){
关闭(管道[i]);
printf(“在子系统中:封闭管道[%d]\n”,i);
}
if(execvp(*命令->参数,命令->参数)<0){
perror(*命令->参数);
退出(退出失败);
}
}否则如果(pid<0){
佩罗(“错误”);
退出(退出失败);
}
命令=命令->下一步;
j+=2;
}
对于(i=0;i<2*numPipes;i++){
关闭(管道[i]);
printf(“在父级中:封闭管道[%d]\n”,i);
}
等待(0);
}
好的,首先,有一点奇怪——你的嵌套没有与大括号对齐。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);
}
}
如果(j!=0){
if(dup2(pipefds[j-2],0)<0){
perror(“dup2”);///j-20j+11
退出(退出失败);
}
如果(命令->下一步){
printf(
if(dup2(pipefds[j+1],1)<0){
perror(“dup2”);
退出(退出失败);
}
}
重新缩进以反映大括号:
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);
}
}
}
如果(j!=0){
if(dup2(pipefds[j-2],0)<0){
perror(“dup2”);///j-20j+11
退出(退出失败);
}
如果(命令->下一步){
printf();/*修复了此问题*/
if(dup2(pipefds[j+1],1)<0){
perror(“dup2”);
退出(退出失败);
}
}
}
请让您的IDE、编辑器或缩进(1)重新缩进代码以反映代码的实际语法,这样您就不会被误导性的空白所迷惑
其次,我认为您在早期迭代中将
j++
从j++
更改为j+=2
,但并没有完全这样做——在第一次调用中,您使用的是pipefds[j-2]
,在下一次调用中,您使用的是pipefds[j+1]
。j-1在第一次迭代中发生了什么?它被忽略。这是故意的吗?j
只在下一次迭代中被引用(通过j+=2..[j-2]
)。有什么会引用pipefds[]中的下一个到最后一个条目吗
?这也是故意的吗?这是问题的答案。希望它能帮助其他人。我最终决定将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);
}
void runPipedCommands(cmdLine*命令,char*用户输入){
int numPipes=countPipes(用户输入);
智力状态;
int i=0;
pid_t pid;
int pipefds[2*numPipes];//声明管道
/**架设管道*/
对于(i=0;i<(numPipes);i++){
如果(管道(管道FDS+i*2)<0){
佩罗尔(“不会吹管”);
退出(退出失败);
}
}
int j=0;
while(命令){
pid=fork();
如果(pid==0){
//如果