exec *的argv可以在多个位置包含值0吗?

时间:2018-04-07 21:44:17

标签: linux x86 exec posix abi

exec创建新流程后,我正在阅读

  

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

如果数组argv中的其他值恰好为0,会发生什么?子进程运行时,是否会错误地计算参数的数量(argc)?

我在AMD64的ABI第34页(https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf)上看到了这一点。

1 个答案:

答案 0 :(得分:3)

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

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。如果NULL中的第一个argv后面还有其他指针,则会忽略它们。有多个NULL气味就像构建argv的程序中的错误一样。
  • 当指针数大于或等于MAX_ARG_STRINGS时,defined0x7FFFFFFF。在这种情况下,系统调用失败。

i返回时,argc返回的值会分配给get_user_arg_ptr

NULL中的终止argv很重要的另一种情况是应用程序本身使用argv,如下所示:

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

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

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