3

我的程序应该使用 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没有任何反应;只是打印语句。有什么建议吗?

4

2 回答 2

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;
于 2016-09-04T01:32:30.470 回答
1

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

...
for(int i=1; i<argc; i++){
    argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
...
于 2016-09-04T01:34:46.507 回答