试图理解for循环中execlp的行为

时间:2014-11-09 13:08:04

标签: c linux exec

main(int argc,char **argv)
{
    int i;
    for(i=1;i<argc;i++)
    {
        execlp(argv[i],"",NULL);
    }
}

我想从命令行输入同时执行多个命令。 所以,在命令行中我给了./a.out date & cal & pwd & ls

在输出中,我可以同时执行所有命令。

但是当我第一次调用execlp时,它应该采用第一个参数,即argv [1],并且应该按进程日期替换整个进程,并且应该在执行后终止整个进程。但如果它终止,那怎么能再次继续for循环?

3 个答案:

答案 0 :(得分:1)

for循环不会继续。只运行第一个命令,并在运行execlp时替换该进程(假设成功)。

但是如果你打印argc的值,你会发现它等于2,即即使没有execlp调用,for循环也只会运行一次迭代。这是因为在shell中,当您运行a & b & c &时,它将分别在后台运行每个命令abc。在这种情况下,它使用命令行./a.out date调用您的流程。其他命令由shell直接运行,而不是由您的进程运行。

答案 1 :(得分:1)

运行calpwdls的程序不是您的程序,它是您正在使用的shell。它使用唯一的参数date调用您的程序,并在后台运行它。然后在后台启动calpwdls

如果您希望程序将它们作为参数接收,请删除&或将它们放在引号中。然后你会看到你的程序确实没有运行循环(除非execl失败)。

答案 2 :(得分:1)

阅读execlp(3)的文档(更常见的是您正在使用的每个函数)。另请阅读Advanced Linux Programming

如果您想将datecalpwdls传递到您的计划a.out,则需要运行命令a.out date cal pwd ls (没有任何&shell解释。 shell是您程序的globbing参数。请参阅glob(7)

顺便说一句,请不要将您的计划命名为a.out。使用像

这样的东西
gcc -Wall -Wextra -g yourprog.c -o yourprog

编译代码然后运行./yourprog(可能在gdb调试器内)。

execlp函数调用在成功时未返回的execve(2)系统调用。因此execlpexecve只会在失败时返回。

因此,当您第一次执行循环时,程序会停止,因为date已成功执行(这意味着date已将替换为 ./yourprog process)。

也许你想要执行一系列程序,直到找到一个程序(例如./yourprog silly date,而你的系统中不存在silly。然后你应该编写像

这样的代码
for(i=1;i<argc;i++) {
    execlp(argv[i],"",NULL);
    // this is reached only if the above `execlp` failed, so
    perror(argv[i]);
}

更有可能的是,您希望依次执行每个程序(例如./yourprog date id ls)。然后,您需要在循环中调用fork(2) 。您将保留fork的结果,并且应该针对fork的失败进行测试。在子流程中,您可以拨打execve(2)execlp(3)。在父进程中,您需要致电waitpid(2)以避免zombie processes

另一种可能性是您想要一次运行所有程序。你需要两个循环,一个执行fork - s(并将子pids保留在某个数组中),另一个执行wait(2)

如果你想要,例如阅读您在子进程中运行的程序的输出(或编写标准输入),您需要了解pipe(7) - s并在 {之前调用pipe(2) {1}}。如果要并行运行它们并从多个管道读取,则需要使用多路复用系统调用,如poll(2)