我正在尝试使用c语言实现管道。 我正在通过创建子进程
为管道分隔的每个命令执行循环以下是我的代码:
int main(int argc, char **argv)
{
char *cmd,*splitcmd;
int i,j,nargc=0,characters;
char **cmdArray;
size_t bufsize = 1024;
int *pipefd;
int pipeArrCount;
pid_t pid,wpid;
int status = 0;
int savestdoutfd = dup(fileno(stdout));
int savestdinfd = dup(fileno(stdin));
cmd = (char *)malloc(bufsize * sizeof(char));
characters = getline(&cmd,&bufsize,stdin);
// printf("%s%d",cmd,characters);
if(cmd[characters-1]=='\n')
{
// printf("in c");
cmd[characters-1]='\0';
characters--;
}
cmdArray = (char**)malloc(sizeof(char *) * 100);
splitcmd=strtok(cmd,"|");
// printf("%s\n",cmd);
while((splitcmd))
{
cmdArray[nargc] = splitcmd;
if(cmdArray[nargc][(strlen(cmdArray[nargc]))-1]==' ')
cmdArray[nargc][(strlen(cmdArray[nargc]))-1]='\0';
printf("%d %s",nargc,cmdArray[nargc]);
nargc++;
splitcmd = strtok(NULL,"|");
}
pipefd=(int*)malloc(2*nargc*sizeof(int));
printf("%d\n",nargc);
pipeArrCount=2*(nargc-1);
printf("%d\n",pipeArrCount);
//exit(0);
for(i=0;i<pipeArrCount;i)
{
printf("making pipe for process %d\n",i);
pipe(pipefd+i);
i=i+2;
}
//exit(0);
for(i=0;i<nargc;i)
{
printf("parent count %d\n",i);
if(i==0)
{
printf("Creating child %d\n",i);
// As it is first process we need to make write end of the pipe as stdout.
if ((pid=fork()) == 0)
{
printf("Creating first child %d for command %s\n",i,cmdArray[i]);
printf("EXECUTING FIRST PROCESS\n");
printf("Writing in pipe[%d]\n",2*i+1);
//close(pipefd[0]);
dup2(pipefd[2*i+1],fileno(stdout));
//closing all other pipes
for(j=0;j<(2*nargc);j++)
{
//if(j!=2*i+1)
close(pipefd[j]);
}
system(cmdArray[i]);
//dup2(savestdoutfd,fileno(stdout));
printf("Stdout is again restored\n");
//printf("pipe [%d] contains %d ",2*i+1,pipefd[2*i+1]);
exit(0);
}
}
else if(i!=nargc-1)
{
if (fork() == 0)
{
printf("EXECUTING MIDDLE PROCESS\n");
printf("Command to execute %s \n",cmdArray[i]);
printf("Reading from pipe[%d]\n",(2*(i-1)));
printf("writing on pipe[%d]\n",(2*i)+1);
dup2(pipefd[(2*(i-1))], 0); //Read end of the previous process pipe as stdin
dup2(pipefd[(2*i)+1], 1); //Write end of the pipe of current process as stdout
//closing all other pipes
for(j=0;j<(2*nargc);j++)
{
//if((j!=(2*(i-1))) && (j!=(2*i)+1))
close(pipefd[j]);
}
system(cmdArray[i]);
exit(0);
}
}
else
{
if (fork() == 0)
{
printf("Creating last child %d for command %s\n",i,cmdArray[i]);
printf("Reading from pipe[%d]\n",(2*(i-1)));
//close(pipefd[1]);
dup2(pipefd[(2*(i-1))],fileno(stdin)); //Read from the end of the previous process pipe as stdin
//printf("EXECUTING LAST PROCESS\n");
//closing all other pipes
for(i=0;j<(2*nargc);j++)
{
//if(j!=(2*(i-1)))
close(pipefd[j]);
}
dup2(savestdoutfd,fileno(stdout));
close(savestdoutfd);
system(cmdArray[i]);
dup2(savestdinfd,fileno(stdin));
close(savestdinfd);
exit(0);
}
}
i=i+1;
sleep(1);
}
while ((wpid = wait(&status)) > 0);
}
没有得到第二个命令的任何输出 现在我正试图执行这个&#39; A | B&#39;命令类型 如果执行代码
,则必须在命令和管道之间留出空格答案 0 :(得分:0)
我执行了你的代码。它适用于单管道,如:
ls | grep "a" and ls | wc.
它不适用于像ls | grep "a" | wc
这样的双重管道。
错误是错误的文件描述符。
我没有调试这个错误,似乎在&#34中有一些错误处理文件描述符;否则如果&#34;条款。你问题的任何方式都不适用于像A | B
这样的单一管道。但确实如此。
希望这有帮助。
答案 1 :(得分:0)
你没有那么正确的解决方案。但首先是一些通用的评论:
cmd = malloc(bufsize * sizeof(char));
for(i=0;i<pipeArrCount;i+=2)
删除i=i+2
,因为它是C中更常见的用法,或至少for(i=0;i<pipeArrCount;)
以避免出现警告。现在是你问题的真正原因。您为管道分配了一个大小为2*nargc
的数组,但只初始化2*(nargc-1)
。最后2个没有被初始化,这应该是无害的,但你关闭整个数组(for(j=0;j<(2*nargc);j++)
。在我的测试中,它们是0(可能是因为调试模式)所以你关闭stdin为您的孩子。只需使用:
for(j=0;j<pipeArrCount;j++)
{
close(pipefd[j]);
}
这不是全部。你在最后一个命令中有一个拼写错误,你用for(i=0;j<(2*nargc);j++)
而不是i
写了j
。如Kulwant Singh所述,它没有关闭允许代码只运行2个命令的任何内容。
您还必须关闭父进程中的管道。该计划的结束应该是:
//closing all pipes
for (j=0; j<pipeArrCount; j++) {
close(pipefd[j]);
}
while ((wpid = wait(&status)) > 0);
}