我正在尝试使用我从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);
}
答案 0 :(得分:2)
好的,首先,有些奇怪的东西 - 你的嵌套不符合你的牙箍。 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[]
中的倒数第二个条目吗?这是故意的吗?
答案 1 :(得分:0)
这是问题的答案。希望它可以帮助那里的人。我最终决定将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);
}