C中的多管道bash样式
我知道有很多线程都在讨论这个问题,但我真的不明白如何解决这个问题 我正在尝试制作一个可以执行linux命令的shell,比如ps | grep | less 我已经完成了解析,将每个命令及其参数放入一个简单的链表中 这是我的实现,它不起作用。希望这足够清楚C中的多管道bash样式,c,shell,unix,pipe,C,Shell,Unix,Pipe,我知道有很多线程都在讨论这个问题,但我真的不明白如何解决这个问题 我正在尝试制作一个可以执行linux命令的shell,比如ps | grep | less 我已经完成了解析,将每个命令及其参数放入一个简单的链表中 这是我的实现,它不起作用。希望这足够清楚 if ((son = fork()) < 0) return printerr_sys("Unable to fork", 0); if (son == 0) { if (first > 1 &&
if ((son = fork()) < 0)
return printerr_sys("Unable to fork", 0);
if (son == 0)
{
if (first > 1 && data->format[first - 1] &&
is_directing_elt(data->format[first - 1]) == DIRECT_TPIPE)
dup2(tube_p[0], STDIN_FILENO);
first = make_argv(data, first, &argv);
if (next)
{
dup2(tube_v[1], STDOUT_FILENO);
close(tube_v[0]);
}
if (execvp(argv[0], argv) < 0)
return printerr_cmd(argv[0], 1);
}
else
{
if (next)
{
close(tube_v[1]);
cmdline_executer(data, next, tube_v);
}
waitpid(son, &(data->lastcmd), WUNTRACED);
data->lastcmd = WEXITSTATUS(data->lastcmd);
}
return TRUE;
我的问题是:
正确的实施方式是什么?
可以用递归来实现吗?
我需要从右到左还是从左到右分叉,逻辑上它会给出相同的结果?
进程独立运行,因此您需要在fork之前为至少第一对命令设置管道,但您在子进程中这样做==0。您可以编写一个递归解决方案,只要剩下至少两个命令,就可以创建一个管道,然后分叉,然后运行第一个命令。进程独立运行,因此您需要在分叉之前为至少第一对命令设置管道,但您是在子命令==0中这样做的。您可以编写一个递归解决方案,只要剩下至少两个命令,就可以创建一个管道,然后分叉,然后运行第一个命令。这是我在计算机科学生涯中必须用C为操作系统主题实现的UNIX Shell的一部分 这可能是一个小问题,我没有检查fork是否<0,等等,但主要思想是正确的 >可以用递归来实现吗
大多数情况下,如果我不使用递归就可以编写类似的可理解代码,我会尽量避免递归 在我的计算机科学生涯中,我必须用C语言为操作系统主题实现UNIX Shell的一部分 这可能是一个小问题,我没有检查fork是否<0,等等,但主要思想是正确的 >可以用递归来实现吗
大多数情况下,如果我不使用递归就可以编写类似的可理解代码,我会尽量避免递归 哦,天哪,对不起,我认错了。希望这是允许的。请将代码放入代码块并格式化。编辑您的帖子并在每行前面添加四个空格。sh从左向右分叉,我相信它只关心最右边的过程,假设它退出后,所有其他进程都将很快消失,并显示一个SIGPIPE,假设您正确关闭了所有管道。@只需Jake或高亮显示所有代码,然后按“代码格式”按钮1和0图标。别担心,Stack Overflow的markdown编辑器实际上工作得很好:哦,天哪,很抱歉出现这种情况。希望这是允许的。请将代码放入代码块并格式化。编辑您的帖子并在每行前面添加四个空格。sh从左向右分叉,我相信它只关心最右边的过程,假设它退出后,所有其他进程都将很快消失,并显示一个SIGPIPE,假设您正确关闭了所有管道。@只需Jake或高亮显示所有代码,然后按“代码格式”按钮1和0图标。别担心,Stack Overflow的markdown编辑器实际上工作得很好:很难找到实现的任何线索?我认为我写的是一个很大的线索。我脑海中浮现出:runcmdsinpipe,list{ifinpipe reopen stdin使用inpipe;iflist->next{create outpipe;fork;runcmdsoutpipe,list->next;reopen stdout使用outpipe;}exec*list;}并用runcmdsnall,list启动它。也许runcmds应该像它做的第一件事一样分叉。很难找到一个实现任何线索?我认为我写的是一个相当大的线索。我脑海中浮现出:runcmdsinpipe,list{ifinpipe reopen stdin使用inpipe;iflist->next{create outpipe;fork;runcmdsoutpipe,list->next;reopen stdout使用outpipe;}exec*list;}并用runcmdsnall,list启动它。也许runcmds应该像它做的第一件事一样分叉。
/* Executes the command 'buffer' assuming that doesn't contain redirections */
void execute_only_pipes(char* buffer)
{
char *temp = NULL, *pipeCommands[MAX_PIPES], *cmdArgs[MAX_ARGUMENTS];
int newPipe[2], oldPipe[2], pipesCount, aCount, i, status;
pid_t pid;
pipesCount = -1; /* This variable will contain how many pipes the command contains */
/* Counting the number of pipes and splitting them into pipeCommands */
do
{
temp = strsep(&buffer, "|");
if(temp != NULL)
{
if(strlen(temp) > 0)
{
pipeCommands[++pipesCount] = temp;
}
}
} while(temp);
cmdArgs[++pipesCount] = NULL;
for(i = 0; i < pipesCount; i++) /* For each command */
{
aCount = -1;
/* Parsing command & arguments */
do
{
temp = strsep(&pipeCommands[i], " ");
if(temp != NULL)
{
if(strlen(temp) > 0)
{
/* If a parameter is ~, then replace it by /home/user */
if (!strcmp(temp, "~"))
strcpy(temp, home);
cmdArgs[++aCount] = temp;
}
}
} while(temp);
cmdArgs[++aCount] = NULL;
/* If there still are commands to be executed */
if(i < pipesCount-1)
{
pipe(newPipe); /* just create a pipe */
}
pid = fork();
if(pid == 0) /* Child */
{
/* If there is a previous command */
if(i > 0)
{
close(oldPipe[1]);
dup2(oldPipe[0], 0);
close(oldPipe[0]);
}
/* If there still are commands to be executed */
if(i < pipesCount-1)
{
close(newPipe[0]);
dup2(newPipe[1], 1);
close(newPipe[1]);
}
/* Execute it */
int res = execvp(cmdArgs[0], cmdArgs);
if (res == -1)
{
printf("Error. Command not found: %s\n", cmdArgs[0]);
}
exit(1);
}
else /* Father */
{
/* If there is a previous command */
if(i > 0)
{
close(oldPipe[0]);
close(oldPipe[1]);
}
/* do we have a next command? */
if(i < pipesCount-1)
{
oldPipe[0] = newPipe[0];
oldPipe[1] = newPipe[1];
}
/* wait for last command process? */
if(i == pipesCount-1)
{
waitpid(pid, &status, 0);
}
}
}
}