execve为什么不启动流程?

时间:2019-11-29 16:21:37

标签: c process fork

我为uni编写了一个方法,该方法应该启动一个程序。我必须使用execve。但这是行不通的。例如,当我使用execvp而不是execve时,它可以工作并启动程序。

#include <stddef.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>

pid_t run_command(char **argv, int no_fork){
    extern char **environ;
    pid_t pid;


    if(no_fork != 0){
        execve(*argv, argv, environ);
        return 0;
    }
    else{
        if((pid = fork()) < 0){
            printf("Error: fork!\n");
            return -1;
        }
        else if(pid == 0){

            argv++;

            printf("execve(%s)\n", *argv);
            execve(*argv, argv, environ);

        }
        else {                                  
            wait(NULL);
        }
    }
    return pid;
}

/*
int run_cmdline(char ** argv){
    return 0;
}*/

int main(int argc, char* argv[]){
    run_command(argv, 0);

    return 0;
}

编译:

clang -o main shell.c

例如执行:

./ main firefox

应启动Firefox。使用execvp且不使用环境时,它可以工作,但对于execve则不行。

感谢您的帮助:)

2 个答案:

答案 0 :(得分:2)

  

execve(* argv,argv,environ);

     

./ main firefox

execve不搜索PATH。您必须提供可执行文件的完整路径或自己解决该路径。这种行为的参考在posix中,但我很难读懂,man execve在我看来更容易。

类似这样:

./main /usr/bin/firefox

应该有效,甚至:

./main /usr/bin/sh -c firefox

或者也许只使用execvp即可自动神奇地获取“父级” environ并搜索路径。还有linux扩展名execvpe,它不在posix中,并且确实使用environ

答案 1 :(得分:0)

您正在使用run_command的参数列表调用main。由于您要运行的程序及其参数位于argv[1]之后,因此您需要检查argc至少为2,然后调用run_command(argv + 1, 0)

编辑

似乎run_command本身会递增argv,但是仅出于某种原因在调用execve的两个代码路径之一中。这两个代码路径应一致地处理参数列表。就个人而言,我认为最好让调用者安排run_command的{​​{1}}引用它应该运行的程序。

如果您坚持要在argv[0]本身中递增argv,以使其run_command引用要运行的程序,那么您需要检查*argv和{{ 1}}都为非空,然后再递增argv[0]。如果调用方负责使argv[1]的{​​{1}}引用要运行的程序,那么最好检查argv是否为空。