免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1568 | 回复: 0
打印 上一主题 下一主题

“参数列表太长”:突破限制 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-12-09 15:55 |只看该作者 |倒序浏览
题目是从这篇文章直译过来的,http://www.linuxjournal.com/article/6060
至于我为什么要写这篇文章,暂且略过不表,也许有些不信任的因素,也许是疑问为什么2002年就有这么详尽的文章解释还有人回问?况且有很多汉化的文章,甚至连linuxsir都有人解决过此问题。总而言之,我也是在重复别人走的路,但是不希望自己对linux的troubleshooting荒废了。
起因:假如你使用的是某个linux发行版,当某个目录下有很多文件时,差不多一万多吧,在执行ls *, mv * ,rm * 等等命令时,终端提示如下的错误:
bash: /bin/ls: Argument list too long
如果你使用的是中文环境,那么报的错是:
bash: /bin/ls: 参数列表太长
这个时候,你会怎么办?google?找以前看过的文档?问熟悉linux的人?从源代码中去寻找答案?......
时间是上述选择的代价,那么最后放弃任何的选择解决问题,也许是最好的办法之一,如果这是一份工作的话,也许会推给别人,也许搁置、搪塞.......
以下是我的一个思路:
google了一把,发现已经有人解决了,从中选出最佳答案,那就是本文首行的链接地址。
以作者的思路,确实可以解决实际问题,并且看到许多的实践者的反馈。
就这样的以解决问题为终结?也许我以前会这样就放弃了,但是这次不会,就像是
[color="#02368d"]ext3固定分区后可以设置inode的数量最大为多少?
我这次同样也不会放弃。在开始之前需要准备三个软件,分别是:coreutils-6.12.tar.gz,bash-3.2.tar.gz,以及glibc-2.4.tar.gz.
思路是这样的,ls是coreutils中的程序,而报的错误是bash,但是bash并没有确定的错误信息是参数,而是属于posix标准的一个错误,那只有glibc了。
http://www.kernel.org/doc/man-pages/online/pages/man3/errno.3.html
我们可以看到如下一行内容:
E2BIG           Argument list too long (POSIX.1)
在glibc中的sysdeps/gnu/errlist.c中可以看到如下语句:
/*
TRANS Argument list too long; used when the arguments passed to a new program
TRANS being executed with one of the @code{exec} functions (@pxref{Executing a
TRANS File}) occupy too much memory space.  This condition never arises in the
TRANS GNU system. */
    [ERR_REMAP (E2BIG)] = N_("Argument list too long"),
# if E2BIG > ERR_MAX
# undef ERR_MAX
# define ERR_MAX E2BIG
# endif
#endif
#ifdef ENOEXEC
/*
好了,报错的信息找到根源了,是什么在使用glibc了呢?由上述参考得一定是kernel所报出的。
然后,就是到kernel-source中,寻找了。
make menuconfig找选项,或是grep .config均不能发现此项。
依然从错误的信息来查找kernel文件,则在include/asm-generic/errno-base.h:#define        E2BIG                 7        /* Argument list too long */
会看这么一行内容。
到此,由于本身功夫的欠缺,我已经无法查下去了,想象用户态陷入内核态,内核返回错误,这一系列复杂的过程。
只好跟着作者去读源码了:
include/linux/binfmt.h
struct pt_regs;
/*
* 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
/* sizeof(linux_binprm->buf) */
#define BINPRM_BUF_SIZE 128
#ifdef __KERNEL__
#define CORENAME_MAX_SIZE 128
/*
* This structure is used to hold the arguments that are used when loading binaries.
*/
struct linux_binprm{
    char buf[BINPRM_BUF_SIZE];
#ifdef CONFIG_MMU
    struct vm_area_struct *vma;
#else
# define MAX_ARG_PAGES  32    struct page *page[MAX_ARG_PAGES];
#endif
    struct mm_struct *mm;
    unsigned long p; /* current top of mem */
    int sh_bang;
    struct file * file;
    int e_uid, e_gid;
    kernel_cap_t cap_inheritable, cap_permitted;
红色部分即是限制参数的缓冲空间大小的参数,我们可以调节MAX_ARG_PAGES、BINPRM_BUF_SIZE 128
来设置具体的值。
更改内核确实是最直接、有效的方法,但是注意:缺点也很明显,如果分配给命令行的内存大于可用的系统内存
,可能导致对系统自身的拒绝服务攻击(
DoS attack
),引起系统崩溃。 尤其是对于多用户系统,即使增加很小
的内存分配都会有很大影响,因为每个用户都被分配到额外内存。因此一定要充分测试来决定是否你的系统可以
使用此方法。
更改内核太过于危险,波及的应用程序太多。建议转换另外的思路。
比如使用find+xargs等构建复杂的命令行。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/6303/showart_1710403.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP