exec* 的 argv 可以在多个地方包含值 0 吗?



我在exec创建一个新进程后读到,

argv是一个参数字符串数组,具有argv[argc] == 0

如果数组中的其他值之一恰好argv为 0,会发生什么情况?当子进程运行时,参数(argc)的数量计算会不正确吗?

我在AMD34(https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf)的ABI的第34页上读到了这篇文章。

execve系统调用(由所有exec*函数使用)具有形式为char *const argv[]的参数。内核通过迭代提供的argv来计算argc,如下所示:

static int count(struct user_arg_ptr argv, int max)
{
int i = 0;
if (argv.ptr.native != NULL) {
for (;;) {
const char __user *p = get_user_arg_ptr(argv, i);
if (!p)
break;
if (IS_ERR(p))
return -EFAULT;
if (i >= max)
return -E2BIG;
++i;
if (fatal_signal_pending(current))
return -ERESTARTNOHAND;
cond_resched();
}
}
return i;
}

该函数实质get_user_arg_ptr计算argv数组中的索引,并返回存储在该索引处的指针。循环在四种情况下中断,其中两种与您的问题相关:

  • 在 argv 数组中看到的第一个NULL。如果在argv的第一个NULL后面有其他指针,它们将被忽略。拥有多个NULL闻起来像构建argv的程序中的一个错误。
  • 当指针数大于或等于MAX_ARG_STRINGS时,定义为0x7FFFFFFF。在这种情况下,系统调用将失败。

返回i的值将分配给get_user_arg_ptr返回时argc

终止NULLargv事务的另一种情况是应用程序本身使用argv,如下所示:

for(char **p = argv; *p != NULL; ++p)
{
// ...
}

它是Linux ABI的一部分,argvNULL终止,因此这样的代码在所有Linux实现中都是合法和可移植的。顺便说一下,这段代码在Windows上也是合法的。因此,提供argc只是为了方便起见。

此外,C 和 C++ 标准分别在 5.1.2.2.1 和 3.6.1 中声明,如果argc大于零,则argv[0]argv[argc-1]中的所有值都应是指向以 null 结尾的字符串的非空指针。此外,argv[argc]必须为 null,并且该argc为非负数。另请参阅此答案。

相关内容

  • 没有找到相关文章

最新更新