C shell中的多个管道
Posted
技术标签:
【中文标题】C shell中的多个管道【英文标题】:multiple piping in C shell 【发布时间】:2014-12-01 07:42:07 【问题描述】:谁能告诉我这段代码有什么问题。当我将该管道输出端用作另一个命令的输入时,我能够成功地写入管道,但无法获得输出。下面是代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> //for pid_t fork() and other system calls
#include <signal.h> //for signal()
#include <sys/types.h>
void command_EXECUTER(char *args[]);
void command_HANDLER(char *args[]);
int pipe_EXECUTER(char *args[], int in, int pos);
void shell_INIT()
int is_interactive = isatty(STDOUT_FILENO);
if(is_interactive)
int main(int argc, char *argv[], char **envp)
char shell_INPUT[1024];
char *tokens[256];
int tok_counts = 0;
while(1)
memset(shell_INPUT,'\0',sizeof(shell_INPUT));
printf("\n%s@%s: ",getenv("USER"),getenv("SESSION"));
fgets(shell_INPUT,1024,stdin);
if((tokens[0] = strtok(shell_INPUT," \n)\t")) == NULL) continue;
tok_counts = 1;
while((tokens[tok_counts] = strtok(NULL, " \n\t")) != NULL) tok_counts++;
/*
int i=0;
while(tokens[i])
printf("%s ",tokens[i]);
i++;
tokens[tok_counts] = NULL;*/
command_HANDLER(tokens);
return 0;
int fileIO_EXECUTER(char *args[], int in, int pos)
int fd;
pid_t pid;
if((pid=fork())==0)
switch(pos)
case 0:
dup2(fd, STDOUT_FILENO);
break;
int pipe_EXECUTER(char *args[], int in, int pos)
int fd[2];
pid_t pid;
pipe(fd);
if((pid=fork())==0)
printf("%s %s %s %d\n",args[0],args[1],args[2],pid);
fflush(stdout);
switch(pos)
case 0: dup2(fd[1], STDOUT_FILENO); //first command
//close(fd[1]);
break;
case 1: dup2(in, STDIN_FILENO); //in between command
dup2(fd[1], STDOUT_FILENO);
//close(fd[1]);
break;
case 2: dup2(in, STDIN_FILENO); //last command
//close(fd[1]);
break;
default: printf("wrong input variable\nexiting");
exit(1);
if(execvp(args[0],args)==-1) printf("%s: command not found",args[0]); fflush(stdout); kill(getpid(),SIGTERM);
else if(pid<0)
printf("couldn't create child");
exit(1);
else
wait(pid);
return fd[0];
void command_EXECUTER(char *args[])
pid_t pid;
if((pid=fork())<0)
printf("couldn't create the child");
exit(1);
else if(pid==0)
if((execvp(args[0],args))==-1) printf("%s: command not found",args[0]); fflush(stdout); kill(getpid(),SIGTERM);
else wait(pid);
void command_HANDLER(char *args[])
int i=0;
int j=0;
char spec_chars[100];
while(args[i])
if((strcmp(args[i],">")==0) || (strcmp(args[i],"<")==0) || (strcmp(args[i],"|")==0) || (strcmp(args[i],"&")==0) || (strcmp(args[i],"$")==0))
spec_chars[j] = *args[i];
j++;
i++;
if(j==0)
if(strcmp(args[0],"exit")==0) exit(0);
else if(strcmp(args[0],"clear")==0) system("clear");
else command_EXECUTER(args);
else
int in = 0;
int h = 0;
int pos=0;
char data[1024];
int k=i;
i = 0;
while(args[i])
if(strcmp(args[i],"|")==0)
args[i] = (char *)NULL;
in = pipe_EXECUTER(args,in,pos);
int n = read(in,data,sizeof(data));
printf("%s %d\n",data,n);
fflush(stdout);
args = args+i+1;
//printf("%s something %s",args[0],args[1]);
pos = 1;
i=0;
else if(strcmp(args[i],"<")==0)
else if(strcmp(args[i],">")==0)
else if(strcmp(args[i],"&")==0)
else
i++;
in = pipe_EXECUTER(args,in,2);
例如,如果我使用
ls |排序
'in' 描述符里面会有 ls 但是 当'sort'访问相同的输出时,它会挂在那里......或者执行该命令的子进程永远不会死,并且由于这个父进程一直在等待。
【问题讨论】:
请编译所有警告和调试信息 (gcc -Wall -Wextra -g
) 然后使用调试器 (gdb
);还针对每个syscalls(2) 测试失败(并在失败时使用perror
)。也可以考虑使用strace
& valgrind
其实我才刚开始,不知道如何使用gdb或其他调试工具..如果你能帮忙..谢谢
不,你需要学习gdb
。这是一项可以使用多年的技能!阅读GDB documentation
嘿,@BasileStarynkevitch 我研究并尝试了所有 gdb、strace 和 valgrind,但仍然没有运气:(
一些错误需要数周才能被发现。祝你好运!不要放弃。休息一下,然后继续寻找你的错误。不要忘记阅读您正在使用的每个系统调用的文档。特别是,您对dup2
的使用是错误的:您没有处理dup2
的失败。另外,请在fork
之前致电fflush
【参考方案1】:
'in' 描述符将在其中包含 ls 但是当相同的输出是 通过“排序”访问它挂在那里
这是由于在父进程中没有关闭管道的写端的疏忽造成的,因为sort
自然会等到所有文件描述符引用写端关闭,确保不再有输入到达。因此,在pipe_EXECUTER()
中,您必须先调用close(fd[1])
,然后再调用return fd[0];
,当然还有调试代码
int n = read(in,data,sizeof(data));
printf("%s %d\n",data,n);
必须删除command_HANDLER()
中的内容,以免消耗sort
的输入。
【讨论】:
以上是关于C shell中的多个管道的主要内容,如果未能解决你的问题,请参考以下文章