C execve()参数

我必须填写以下参数:

int execve(const char *filename, char *const argv[], char *const envp[]); 

如果我执行这个程序:

 #include  int main() { char *args[2]; args[0] = "/bin/sh"; args[1] = NULL; execve(args[0], args, NULL); } 

shell按预期正确生成。

我的问题是,如果我将NULL作为第二个参数传递,那么shell也会正确生成:

 #include  int main() { char *args[2]; args[0] = "/bin/sh"; args[1] = NULL; execve(args[0], NULL, NULL); } 

那么使用args向量(使用“/ bin / sh”+ NULL)作为第二个参数而不是NULL的目的是什么?

在这一行: execve(args[0], NULL, NULL); 你只是使用args数组的第一个元素。 你也可以使用像char* command="/bin/sh" 。 你必须传递一些东西,因为这就是execve()定义方式。 在您的情况下,您传递NULL因为您不需要传递任何东西。

execve()的第二个参数的要点是将参数传递给您正在生成的命令。 假设您只是想执行ls而不是shell,那么您可以传递这些参数:

 #include  int main() { char *args[2]; args[0] = "/bin/ls"; args[1] = "-lh"; execve(args[0], args, NULL); } 

另外,引用man execve

argv是传递给新程序的参数字符串数组。 按照惯例,这些字符串中的第一个应包含与正在执行的文件关联的文件名 。 envp是一个字符串数组,通常格式为key = value,它们作为环境传递给新程序。

如果将空指针作为execve的第二个或第三个参数传递,则根据POSIX,您的程序是不正确的; 这两个参数都必须是非null。 (这并不是execve规范中明确说明的 ,但它就在那里。)我目前正在一个处理传递空指针的操作系统上输入它,

 execve("executable", 0, 0); 

等同于传递空数组,例如

 execve("executable", (char *[]){0}, (char *[]){0}); 

但我不会惊讶地发现其他操作系统会触发分段错误或返回-1并将errno设置为EFAULTEINVAL

允许为这些参数传递空数组,但如果第二个参数是空数组,则新执行的程序将在argc / argv接收零参数,如果第三个参数是空数组,则在envp / environenvp零环境变量。 许多程序在这些条件下会出现故障。 例如,看到类似的东西是很常见的

 int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "usage: %s one two three\n", argv[0]); return 2; } // ... } 

程序隐含地假定argv[0]将始终为非null。

因此,您应该始终为两个参数提供非空数组。 通常的惯例是,如果你没有别的事可做,你可以使用

 execve(program, (char *[]){program, 0}, environ); 

它提供程序自己的名称为argv[0] ,没有其他参数,以及从您自己的父项获得的同一组环境变量。