编辑:
我终于能够将 edit (4))。但是,请仔细阅读我是如何做到的,并自行决定这是否是您想要的方式。至少你应该能够从我的发现中理解为什么你被“卡住”了。
随着ARG_MAX 与ulim -s / 4 的耦合,引入了MAX_ARG_STRLEN 作为最大值。参数的长度:
/*
* linux/fs/exec.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
...
#ifdef CONFIG_MMU
/*
* The nascent bprm->mm is not visible until exec_mmap() but it can
* use a lot of memory, account these pages in current->mm temporary
* for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we
* change the counter back via acct_arg_size(0).
*/
...
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= MAX_ARG_STRLEN;
}
...
#else
...
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= bprm->p;
}
#endif /* CONFIG_MMU */
...
static int copy_strings(int argc, struct user_arg_ptr argv,
struct linux_binprm *bprm)
{
...
str = get_user_arg_ptr(argv, argc);
...
len = strnlen_user(str, MAX_ARG_STRLEN);
if (!len)
goto out;
ret = -E2BIG;
if (!valid_arg_len(bprm, len))
goto out;
...
}
...
MAX_ARG_STRLEN定义为linux/include/uapi/linux/binfmts.h中页面大小的32倍:
...
/*
* These are the maximum length and maximum number of strings passed to the
* execve() system call. MAX_ARG_STRLEN is essentially random but serves to
* prevent the kernel from being unduly impacted by misaddressed pointers.
* MAX_ARG_STRINGS is chosen to fit in a signed 32-bit integer.
*/
#define MAX_ARG_STRLEN (PAGE_SIZE * 32)
#define MAX_ARG_STRINGS 0x7FFFFFFF
...
默认页面大小为 4 KB,因此您不能传递超过 128 KB 的参数。
我现在不能尝试,但如果可能的话,在您的系统上切换到大页面模式(页面大小 4 MB)可能会解决这个问题。
有关更多详细信息和参考资料,请参阅 this answer 至 a similar question on Unix & Linux SE。
编辑:
(1)
根据this answer,可以通过在内核配置中启用CONFIG_TRANSPARENT_HUGEPAGE 并将CONFIG_TRANSPARENT_HUGEPAGE_MADVISE 设置为n,将x86_64 Linux 的页面大小更改为1 MB。
(2)
使用上述配置更改 getconf PAGESIZE 重新编译我的内核后,仍然返回 4096。
根据this answer,还需要CONFIG_HUGETLB_PAGE,我可以通过CONFIG_HUGETLBFS 加入。我现在正在重新编译,将再次测试。
(3)
我重新编译了启用CONFIG_HUGETLBFS 的内核,现在/proc/meminfo 包含the corresponding section of the kernel documentation 中提到的相应HugePages_* 条目。
但是,根据getconf PAGESIZE 的页面大小仍然没有改变。因此,虽然我现在应该能够通过 mmap 调用请求大页面,但确定 MAX_ARG_STRLEN 的内核默认页面大小仍然固定为 4 KB。
(4)
我将linux/include/uapi/linux/binfmts.h 修改为#define MAX_ARG_STRLEN (PAGE_SIZE * 64),重新编译了我的内核,现在你的代码生成了:
...
117037
123196
123196
129680
129680
136505
143689
151251
159211
...
227982
227982
239981
239981
252611
252611
265906
./testCL: line 11: ./foo: Argument list too long
279901
./testCL: line 11: ./foo: Argument list too long
294632
./testCL: line 11: ./foo: Argument list too long
所以现在限制从 128 KB 移动到了 256 KB,正如预期的那样。
不过我不知道潜在的副作用。
据我所知,我的系统似乎运行良好。