【发布时间】:2012-09-22 15:28:10
【问题描述】:
我正在用 C 语言编写一个小型 linux shell,并且非常接近完成。我接收来自用户的命令并将其存储在 args 中,由空格分隔。在以下示例中,假设 args 包含以下内容:
args[] = {"ls", "-l", "|", "wc"};
我的函数接受 args 并接受有多少 管道。我已经尽可能多地注释了我的代码。这里是:
int do_command(char **args, int pipes) {
// The number of commands to run
const int commands = pipes + 1;
int i = 0;
int pipefds[2*pipes];
for(i = 0; i < pipes; i++){
if(pipe(pipefds + i*2) < 0) {
perror("Couldn't Pipe");
exit(EXIT_FAILURE);
}
}
int pid;
int status;
int j = 0;
int k = 0;
int s = 1;
int place;
int commandStarts[10];
commandStarts[0] = 0;
// This loop sets all of the pipes to NULL
// And creates an array of where the next
// Command starts
while (args[k] != NULL){
if(!strcmp(args[k], "|")){
args[k] = NULL;
// printf("args[%d] is now NULL", k);
commandStarts[s] = k+1;
s++;
}
k++;
}
for (i = 0; i < commands; ++i) {
// place is where in args the program should
// start running when it gets to the execution
// command
place = commandStarts[i];
pid = fork();
if(pid == 0) {
//if not last command
if(i < pipes){
if(dup2(pipefds[j + 1], 1) < 0){
perror("dup2");
exit(EXIT_FAILURE);
}
}
//if not first command&& j!= 2*pipes
if(j != 0 ){
if(dup2(pipefds[j-2], 0) < 0){
perror("dup2");
exit(EXIT_FAILURE);
}
}
int q;
for(q = 0; q < 2*pipes; q++){
close(pipefds[q]);
}
// The commands are executed here,
// but it must be doing it a bit wrong
if( execvp(args[place], args) < 0 ){
perror(*args);
exit(EXIT_FAILURE);
}
}
else if(pid < 0){
perror("error");
exit(EXIT_FAILURE);
}
j+=2;
}
for(i = 0; i < 2 * pipes; i++){
close(pipefds[i]);
}
for(i = 0; i < pipes + 1; i++){
wait(&status);
}
}
我的问题是,虽然程序有点正确执行,但它的行为很奇怪,我希望你能帮助我。
例如 hen 我运行 ls | wc,输出是ls | wc,但它也会在其下方打印一个简单的 ls 的输出,即使它应该只是输出的 wc。
作为另一个例子,当我尝试 ls -l | wc,wc的第一个数字出现,但随后ls -l的输出显示在它的下方,即使它应该只是wc 的输出。
提前致谢! :)
【问题讨论】:
-
在这里工作。你确定你用正确的参数调用你的函数吗?
-
在这里也可以正常工作。顺便说一句,
do_command没有按应有的方式返回。 -
有效?!哈哈。它是否 100% 正确工作?就像您在实际的 linux 框中的程序之外键入
ls -l | wc一样,它的输出与我的代码中的输出是否相同? -
我只试过
ls | wc,但是是的,它有相同的输出。 -
存在一个影响
ls -l | wc的错误(实际上是ls -l | wc -l)。除此之外,它对我有用。你应该试试strace -f yourprogram看看它到底做了什么。