我很好地执行像“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 |头-1和ls的其他变化,但当我做ls |的事情排序-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);
}
}
}
答案 0 :(得分:2)
你想做ls | sort
之类的事情,但是你想做的事情
char *arg[] = {"ls","|","sort",NULL};
execvp(arg[0],arg); /*it won't work */
无法工作,因为您在execvp
和ls
拨打sort
,这是两个独立的流程而不是单个流程。还
ls | sort => output of process-1 make as input to process-2 & execute it
| |
process-1 process-2
要实现上述目标,请致电fork()
并使用exec()
系列函数替换子级&{父母过程。
这是示例代码
ls
答案 1 :(得分:1)
|
是一个shell功能。您需要执行shell所做的相同操作,即使用pipe
,fork
,dup2
,execvp
来创建管道,生成新进程并连接管道进程' stdin和stdout分别。
从execString
函数中获取代码,但替换else
块。在父流程中,您应该dup2(link[0], 0)
(将管道的读取端连接到stdin
),然后execvp
其他程序(例如sort
)。
请记住关闭您不需要的管道末端!即在制片人过程中,close(link[0])
;在消费者流程中,close(link[1])
。如果你忘了这一部分,事情就会陷入困境。 (命令看似永远悬挂)。
当然,如果您希望原始程序继续运行,您需要将该代码包含在另一个fork
(以及waitpid
)中。
另外,如果命令输出大量数据,则execString
会被破坏。在某些时候,管道将变满并且命令将暂停,等待另一个过程排空管道(通过读取它)。您的程序将卡在wait
中,等待命令终止。结果是死锁。
要解决此问题,请在完成从管道中读取后调用wait
。