分叉和执行分段错误

时间:2016-09-04 01:20:29

标签: c fork execve

我的程序应该使用fork和exec系统调用。 exec应该更改子进程,以便它将另一个命令作为参数并执行 那个命令。例如,要显示当天的消息:

 ./myexec cat /etc/motd

这是我目前的代码

extern char **environ;      /* environment info */
main(int argc, char **argv) {
     /* argc -- number of arguments */
     /* argv -- an array of strings */

    char *argvNew[argc + 1];
    int pid;

    for(int i=0; i<argc; i++){
        argvNew[i] = argv[i];
    }
    argvNew[argc + 1] = NULL;
    printf("After For: %s\n",argvNew[0]);
    printf("After For: %s\n",argvNew[1]);
    printf("After For: %s\n",argvNew[2]);
    printf("After For: %s\n",argvNew[3]);


    if ((pid = fork()) < 0) {
        fprintf(stderr, "Fork error%sstrerror\n", strerror(errno));

        exit(1);
    }
    else if (pid == 0) {
        /* child process */
        if (execve(argvNew[0], argvNew, environ) < 0) {
            fprintf(stderr, "Execve error%d %s\n",errno,strerror(errno));
            exit(1);
        }
    }
    else {
        /* parent */
    wait(0);        /* wait for the child to finish */
    }

}

运行./myexecv cat etc/motd后没有任何反应;只是印刷声明。有什么建议吗?

2 个答案:

答案 0 :(得分:2)

显示的代码中存在多个错误。

    for(int i=0; i<argc; i++){
            argvNew[i] = argv[i];
    }
    argvNew[argc+1] = NULL;

在它的面值上,NULL赋值是错误的,并且会导致未定义的行为,因为argvNew被声明为

    char *argvNew[argc + 1];

因此,数组包含值argvNew[0]argvNew[argc],并且argvNew[argc+1]=NULL;在数组末尾之外运行,导致未定义的行为。这显然应该是

    argvNew[argc] = NULL;

但即便如此也是错误的,因为:

 execve(argvNew[0], argvNew, environ);

argvNew[0]是从argv[0]复制的,这是正在执行的程序的名称。这将在子进程中分叉并运行相同的程序。

你最终会自行分叉。如果这是一个共享服务器,你将使系统管理员非常生气。

您需要从等式中删除argv[0],然后仅复制argv[1],然后再打开。正确的循环和副本是:

    int pid;
    char *argvNew[argc];

    for(int i=1; i<argc; i++){
            argvNew[i-1] = argv[i];
    }
    argvNew[argc-1] = NULL;

答案 1 :(得分:1)

execve()的调用参数要求第一个参数是要执行的文件名。不幸的是,您传递了argvNew[0],其值与argv[0]相同。这意味着您再次调用并调用自己的程序,而不是脚本。您需要将参数移动一个:

...
for(int i=1; i<argc; i++){
    argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
...