使用不带参数列表的 execv

Using execv without parameters list

我想从我的主程序中使用 fork 来创建我编写的其他程序的进程实例。 这是我正在尝试做的事情的例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>

    int main(int argc, char *argv[]){
    char *ar[] = {"./myfile",NULL};

    switch (fork()) {
        case -1:
            printf("Problem.\n");
            break;
        case 0:
            printf("Everything ok...\n");
            execv("./myfile",ar);
            printf("err\n");
            exit(1);
        default: 
            sleep(1);
    }
    return 0;
}

这是我的主程序。程序 myfile 如下所示:

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    #include <signal.h> 
    #include <unistd.h>

int main(int argc, char *argv[]){
    printf("Hi!\n");
    return 0;
}

这是我期待的输出:

Everything ok...
Hi!

但我只得到:

Everything ok...

我做错了什么? execv 有两个参数,但在我的例子中第二个参数是空的(或 NULL?)。我试图添加行

char *argv[] = NULL;

到我的主程序,但我得到了错误,因为我不能在 C 中这样做。

如果没有终止换行符, 您的程序 中的任何一个的输出都不能保证如您预期的那样出现。始终输出终止 '\n'.

execv 有两个参数,根据手册页,第二个参数需要是:

an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a null pointer.

所以你应该有这样的东西:

char *argv_for_program[] = { filename, NULL };
execv(filename, argv_for_program);

一些其他注意事项:

  • 紧接在 execv 之前的 printf 没有以换行符结尾。由于 stdout 通常是 line buffered,因此在刷新缓冲区之前不会打印文本 "Everything ok..."execv./myfile 替换了你的程序,没有刷新缓冲区,所以 "Everything ok..." 消息丢失了。要解决此问题,请改为打印 "Everything ok...\n",或在 execv.

  • 之前调用 fflush(stdout)
  • execv 仅 returns 如果您 未能 执行该程序。在这种情况下,exit(EXIT_SUCCESS) 可能是不可取的;最好打印一条适当的错误消息(例如 perror)并以失败代码退出。

  • 如评论中所述,您需要 #include <unistd.h>.

如果您想通过 argv[] 提供参数(正如您在评论中指出的那样),只要您提供 Full-Path 到 运行 的程序作为第一个参数和此后传递给该程序的任何参数。 argv 已经是一个指针数组,最后一个用户提供的参数后的第一个指针设置为 NULL。您只需在 argv[1] 处开始索引(argv[0] 始终是当前程序 运行,argv[1] 第一个用户提供的参数)您可以做一些简单的事情:

#include <stdio.h>
#include <unistd.h>

int main (int argc, char **argv) {

    if (argc < 2) {
        fprintf(stderr, "error: insufficient input.\n"
                        "usage: %s full-path-prog [arg1, arg2, ...]\n", argv[0]);
        return 1;
    }

    execv (argv[1], &argv[1]);      /* call execv with argv[] */
}

(注意:成功时,execv不return,新进程替换当前进程,失败时,你实际上应该调用_exit(); 如果你设置了 atexit() 函数或析构函数,则避免极端情况 UB -- 此处不相关)

只要您提供有效的实用程序名称和参数(不包括任何重定向等),代码就会将实用程序简单地传递给 execv,并且它将使用提供的任何其他参数执行, 例如

例子Use/Output

提供程序的完整路径和任何参数,例如

$ ./bin/execv_simple /bin/ls -al /home/david/tmp
total 1163032
drwxr-xr-x 44 david david         20480 Mar 23 13:35  .
drwxr-xr-x 68 david david          4096 Mar 25 02:36  ..
drwxr-xr-x  2 david david          4096 Nov  7 22:30  .qt
-rw-r--r--  1 david david       4534793 Nov  4 19:31  .xsession-errors
...

$ ./bin/execv_simple /usr/bin/df -h
Filesystem     1K-blocks     Used Available Use% Mounted on
devtmpfs         4043708        0   4043708   0% /dev
tmpfs            4055092    11964   4043128   1% /dev/shm
tmpfs            4055092     1716   4053376   1% /run
tmpfs            4055092        0   4055092   0% /sys/fs/cgroup
/dev/sdb2       41156156 25400864  13641604  66% /
tmpfs            4055092       60   4055032   1% /tmp
/dev/sdb3      437217592 43731284 392581260  11% /home
tmpfs             811016        8    811008   1% /run/user/1000

$ ./bin/execv_simple /usr/bin/free
              total        used        free      shared  buff/cache   available
Mem:        8110188     2147572     4048728       53432     1913888     5594460
Swap:       2103292           0     2103292

(注意: 您可以使用 命令替换 type -pwhich 来提供完整的程序名称,例如 ./bin/execv_simple $(type -p free) 将为您填写完整路径信息)

未提供参数:

$ ./bin/execv_simple
error: insufficient input.
usage: ./bin/execv_simple full-path-prog [arg1, arg2, ...]

检查一下,如果您还有其他问题,请告诉我。