swd*_*dev 5 linux shell amazon-sqs
我必须将256Kb的文本作为参数传递给"aws sqs"命令,但是在命令行中运行的限制大约为140Kb.这在许多地方已经讨论过,它已经在Linux内核中从2.6.23内核中解决了.
但无法让它发挥作用.我在用3.14.48-33.39.amzn1.x86_64
这是一个简单的测试示例:
#!/bin/bash
SIZE=1000
while [ $SIZE -lt 300000 ]
do
echo "$SIZE"
VAR="`head -c $SIZE < /dev/zero | tr '\0' 'a'`"
./foo "$VAR"
let SIZE="( $SIZE * 20 ) / 19"
done
Run Code Online (Sandbox Code Playgroud)
而foo
剧本只是:
#!/bin/bash
echo -n "$1" | wc -c
Run Code Online (Sandbox Code Playgroud)
而我的输出是:
117037
123196
123196
129680
129680
136505
./testCL: line 11: ./foo: Argument list too long
143689
./testCL: line 11: ./foo: Argument list too long
151251
./testCL: line 11: ./foo: Argument list too long
159211
Run Code Online (Sandbox Code Playgroud)
那么,如何修改testCL
脚本的问题是它可以传递256Kb的数据?顺便说一句,我已经尝试添加ulimit -s 65536
到脚本,它没有帮助.
如果这是完全不可能的,我可以解决这个问题,但是你可以从上面的链接中阐明这个引用
"虽然Linux不是Plan 9,但在2.6.23中Linux正在添加变量参数长度.理论上你不应该经常点击"参数列表太长"错误,但是这个补丁也将最大参数长度限制为最大值的25%堆栈限制(ulimit -s)."
编辑:
我终于能够将 <= 256 KB 作为单个命令行参数传递(请参阅底部的编辑 (4) )。但是,请仔细阅读我是如何做到的,并自行决定这是否是您想要的方式。至少你应该能够从我的发现中理解为什么你会被“卡住”。
ARG_MAX
随着to / 4的耦合,ulim -s
引入了MAX_ARG_STRLEN
as max。参数的长度:
/*
* linux/fs/exec.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
Run Code Online (Sandbox Code Playgroud)
...
#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).
*/
Run Code Online (Sandbox Code Playgroud)
...
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= MAX_ARG_STRLEN;
}
Run Code Online (Sandbox Code Playgroud)
...
#else
Run Code Online (Sandbox Code Playgroud)
...
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= bprm->p;
}
#endif /* CONFIG_MMU */
Run Code Online (Sandbox Code Playgroud)
...
static int copy_strings(int argc, struct user_arg_ptr argv,
struct linux_binprm *bprm)
{
Run Code Online (Sandbox Code Playgroud)
...
str = get_user_arg_ptr(argv, argc);
Run Code Online (Sandbox Code Playgroud)
...
len = strnlen_user(str, MAX_ARG_STRLEN);
if (!len)
goto out;
ret = -E2BIG;
if (!valid_arg_len(bprm, len))
goto out;
Run Code Online (Sandbox Code Playgroud)
...
}
Run Code Online (Sandbox Code Playgroud)
...
MAX_ARG_STRLEN
被定义为页面大小的 32 倍linux/include/uapi/linux/binfmts.h
:
...
/*
* 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
Run Code Online (Sandbox Code Playgroud)
...
默认页面大小为 4 KB,因此您不能传递超过 128 KB 的参数。
我现在无法尝试,但如果可能的话,在您的系统上切换到大页面模式(页面大小 4 MB)也许可以解决此问题。
有关更详细的信息和参考,请参阅Unix & Linux SE 上类似问题的答案。
编辑:
(1)
根据这个答案,可以通过在内核配置中和设置来的页面大小更改x86_64
为 1 MBCONFIG_TRANSPARENT_HUGEPAGE
CONFIG_TRANSPARENT_HUGEPAGE_MADVISE
n
(2)
使用上述配置更改重新编译内核后,getconf PAGESIZE
仍然返回 4096。根据这个答案 CONFIG_HUGETLB_PAGE
,我也可以通过 拉入CONFIG_HUGETLBFS
。我现在正在重新编译并再次测试。
(3)
我重新编译了启用的内核CONFIG_HUGETLBFS
,现在包含内核文档相应部分中提到的/proc/meminfo
相应。然而,页面大小仍然没有改变。因此,虽然我现在应该能够通过调用请求大页面,但内核的默认页面大小确定仍然固定为 4 KB。HugePages_*
getconf PAGESIZE
mmap
MAX_ARG_STRLEN
(4)
我修改linux/include/uapi/linux/binfmts.h
为#define MAX_ARG_STRLEN (PAGE_SIZE * 64)
,重新编译了我的内核,现在你的代码生成:
...
117037
123196
123196
129680
129680
136505
143689
151251
159211
Run Code Online (Sandbox Code Playgroud)
...
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
Run Code Online (Sandbox Code Playgroud)
因此,现在限制如预期从 128 KB 变为 256 KB。但我不知道潜在的副作用。据我所知,我的系统似乎运行得很好。
归档时间: |
|
查看次数: |
3113 次 |
最近记录: |