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

标签 linux x86 exec posix abi

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

argv is an array of argument strings, with argv[argc] == 0

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

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

最佳答案

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

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 的索引数组并返回存储在该索引处的指针。循环在四种情况下中断,其中两种与您的问题相关:

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

i的值返回的值被分配给 argcget_user_arg_ptr返回。

另一种情况是终止 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是非负的。另请参阅this回答。

关于linux - exec* 的 argv 可以在多个地方包含 0 值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49712252/

相关文章:

assembly - 为什么 `call dword 0x12345678` 会编译成 [66,E8,72,56,34,12]?

linux-kernel - in_irq() 可靠吗?

php - Amazon Linux 上的多个 PHP-FPM 版本加载相同的配置

c - 使用 exec() 函数在 C 中调用 Linux 命令

assembly - 组装中的随机数

Ruby Net::SSH 使用变量插值更改目录

php shell_exec($cmd) 不在 cronjob 中运行

java - 如何从 java 控制台运行控制台应用程序?

linux - 蓝牙RFCOMM连接Linux

linux - 在 Linux 上将格式错误的 PDF 批量转换为 TIF