[英]C executing a command with another commands output with execvp
我可以很好地执行“ ls”之类的命令,但我想执行“ ls | sort”之类的东西,但是execvp系统调用不支持“ |”。 如何仅使用系统调用来做到这一点? 当我尝试类似
char *arg[] = {"ls","|","sort",NULL};
execvp(arg[0],arg);
它不起作用,我该怎么办?
编辑:
char* execString (char string[]){
int link[2];
pipe(link);
if (fork() == 0){
int i = 0;
char *p = strtok(string," ");
char *x[spacecount(string)+2];
while(p){
x[i++] = p;
p = strtok(NULL," ");
}
x[i] = NULL;
dup2(link[1],1);
close(link[0]);
close(link[0]);
execvp(x[0],x);
_exit(0);
} else {
wait(NULL);
close(link[1]);
char buf[512];
int i = 0;
while (read(link[0],&buf[i++],1) == 1);
close(link[0]);
buf[i-2] = '\0';
return strdup(buf);
}
}
这是我正在执行的函数,用于执行包含命令的字符串,其返回值是指向包含该命令输出的字符串的指针,如何使用execvp将该输出作为新命令的输入? exec系列的另一个功能?
Edit2:所以我做了一个新的函数,它接收两个字符串作为参数,并执行第一个,然后使用第一个exec的输出作为输入来执行第二个,我认为与ls | | | | | | | head -1和ls的其他变体,但是当我做ls | sort -R它不起作用,我已经尝试了好几件事,但我不明白为什么会这样,下面是代码:
char* execStrings (char previousstring[], char string[]){
int link[2];
pipe(link);
if (fork() == 0){
int i = 0;
char *previouscommand[spacecount(previousstring)+2];
char *temp = strtok(previousstring," ");
while(temp){
previouscommand[i++] = temp;
temp = strtok(NULL," ");
}
previouscommand[i] = NULL;
dup2(link[1],1); /* stdout result redrecting to write end of pipe */
close(link[1]);
close(link[0]);
execvp(previouscommand[0],previouscommand);
} else {
wait(NULL);
int res[2];
pipe(res);
if(fork() == 0){
int i = 0;
char *temp = strtok(string," ");
char *command[spacecount(string)+2];
while(temp){
command[i++] = temp;
temp = strtok(NULL," ");
}
command[i] = NULL;
dup2(link[0],0);
close(link[0]);
close(link[1]);
dup2(res[1],1);
close(res[1]);
close(res[0]);
execvp(command[0],command)
} else {
wait(NULL);
close(res[1]);
char buf[512];
int i = 0;
while (read(res[0],&buf[i++],1) == 1);
close(res[0]);
buf[i-2] = '\0';
return strdup(buf);
}
}
}
您想做ls | sort
事情ls | sort
ls | sort
但你的行为方式像
char *arg[] = {"ls","|","sort",NULL};
execvp(arg[0],arg); /*it won't work */
将不起作用,因为在这里您在ls
上调用execvp
并进行sort
,这是两个单独的进程而不是单个进程。 也
ls | sort => output of process-1 make as input to process-2 & execute it
| |
process-1 process-2
要实现上述目的,可以通过调用fork()
创建两个进程,并使用exec()
系列函数替换ls
并在子进程和父进程中进行sort
。
这是示例代码
int main(void) {
int p[2];
pipe(p);
char *arg[] = {"ls","sort",NULL};
if(fork()==0) {
close(0);/* close the stdin stream so that this
process shoulbn't read from stdin */
dup(p[0]);/* read from read end of pipe */
close(p[1]);
execlp(arg[1],arg[1],(char*)NULL);
}
else{
close(1);/* close the stdout stream, so that o/p shouldn't print on monitor */
dup(p[1]); /* stdout result redrecting to write end of pipe */
close(p[0]);
execlp(arg[0],arg[0],(char*)NULL);
}
return 0;
}
|
是外壳功能。 您需要做与外壳程序相同的操作,即使用pipe
, fork
, dup2
, execvp
创建一个管道,生成一个新进程,并将该管道分别连接到进程的stdin和stdout。
从execString
函数中获取代码,但替换else
块。 在父进程应该dup2(link[0], 0)
连接你的管道的读端stdin
),然后execvp
其他程序(如sort
)。
记住关闭不需要的管端! 即在生产者过程中, close(link[0])
; 在使用者进程中, close(link[1])
。 如果您忘记了这一部分,事情可能会“卡住”(命令似乎永远挂着)。
当然,如果你希望你的原来的程序继续下去,你需要用另一种内部的代码fork
(和waitpid
为它)。
execString
,如果命令输出大量数据,则execString
会损坏。 在某个时候,管道将充满,命令将暂停,等待另一个进程将管道排空(通过读取管道)。 您的程序将停留在wait
,等待命令终止。 结果是死锁。
要解决此问题,请在完成从管道中的读取后仅调用wait
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.