【问题标题】:Passing an argument using execvp使用 execvp 传递参数
【发布时间】:2015-03-18 00:50:22
【问题描述】:

我的 parent.c 文件中有这个

int main()
{
int n = 6;
int pid;
int status;
char* command = "./child";
for (i=1; i<=n; i++){


    if((pid = fork()) == 0) {
        execvp(command, NULL);
    }
    wait(&status);
}

我的 child.c 文件如下所示

int main(int argc, char *argv[]){
    char *processnum = argv[0];
    printf("This is the child %s\n", processnum);
    return 0;
}

我基本上只是跑了

gcc -o parent parent.c

gcc -o child child.c

./父母

这会打印 6 次“This is the child (null)”,这是我所期望的。但是我希望能够在运行 child 时传递一个参数,在这种情况下是进程号。

所以我把我的 parent.c 改成这样

for (i=1; i<=n; i++){
    if(i == 1){
        char* args = "1";
    }
    if(i == 2){
        char* args = "2";
    }
    if(i == 3){
        char* args = "3";
    }
    if(i == 4){
        char* args = "4";
    }
    if(i == 5){
        char* args = "5";
    }
    if(i == 6){
        char* args = "6";
    }

    if((pid = fork()) == 0) {
        execvp(command, args);
    }
    wait(&status);
}

我认为会发生的是我的程序会打印“这是孩子 1”、“这是孩子 2”等...

但是,实际发生的情况是程序似乎多次运行 parent.c(我在 parent.c 的开头放置了一个打印语句,输出打印了 20 次该语句)而不是 child.c

谁能解释为什么会这样?还有其他方法可以将参数传递给 child.c 吗?

谢谢

【问题讨论】:

  • 您为什么期望argv[0] 的值是01execvp 的手册页解释了如何传递参数。您传递的内容不正确。它需要char *argv[](指向参数指针数组的指针)。顺便说一句,您的if 语句字符串将作为switch 语句完成。
  • 最初我尝试设置 command = "./child 6" 例如,我希望 argv[0] 将存储 6 并且我可以在孩子中使用它,但它不起作用
  • 如果您阅读execvp 的文档,它应该会澄清一些事情。

标签: c gcc fork execvp


【解决方案1】:
here is the critical excerpt from the man page for execvp()

   The execv(), execvp(), and execvpe()  functions  provide  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.

【讨论】:

    【解决方案2】:

    您的程序存在几个问题。首先,正如其他人所描述的, execvp 的第二个参数是一个 char ** 类型......它最终作为被执行程序中的 argv。

    其次, 如果(我 == 1){ 字符* args = "1"; } ... 代码设置一个变量 args,其范围在下一行结束。您必须在要使用它的范围内声明 args。

    第三,像这样将数字转换为字符串是非常有限且乏味的!使用标准 C 函数 sprintf(甚至更好的 snprintf)会做得更好。

    这是一个更新的 parent.c:

    #include <sys/wait.h>
    #include <stdio.h>
    #include <unistd.h>
    
    int main()
    {
            int n = 6;
            int pid;
            int status;
            char* command = "./child";
            char *child_args[2];
            char number_buff[32];   // more than big enough to hold any number!
    
            child_args[1] = NULL;
            for (int i=1; i<=n; i++){
                    sprintf(number_buff, "%d", i);
                    child_args[0] = number_buff;
                    if((pid = fork()) == 0) {
                            execvp(command, child_args);
                    }
                    wait(&status);
            }
            return 0;
    }
    

    【讨论】:

      【解决方案3】:

      谁能解释为什么会这样?还有其他方法可以将参数传递给 child.c 吗?

      您应该将 char* 数组传递给 execvp,而不是 char*。如 cmets 中所述,数组的最后一个元素应该是空指针。以下应该有效:

      char* args[] = {"1\0", NULL};
      execvp(command, args);
      

      我猜测 execvp 失败了,因为它无法将 args 取消引用为 char**,因此分叉的进程作为父进程继续循环。您应该检查 execvp 的返回值以查看函数调用是否有效。

      此外,command 和 args 应该以 null 结尾。我建议使用函数itoa 将int 转换为c 字符串。

      【讨论】:

      • 传递给 execvp() 的参数是:1)要执行的文件的路径/名称 2)传递的第三个参数中的条目数 3)指向指针数组的指针C 字符串,最后一项为 NULL。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 2012-05-24
      • 2011-04-22
      • 2013-10-14
      • 2012-04-28
      相关资源
      最近更新 更多