編集:
最終的に <=256 KB を単一のコマンドライン引数として渡すことができました (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) に切り替えると、この問題が解決するかもしれません。
より詳細な情報とリファレンスについては、Unix &Linux SE に関する同様の質問に対するこの回答を参照してください。
編集:
(1) この回答によると、 x86_64
のページサイズを変更できます CONFIG_TRANSPARENT_HUGEPAGE
を有効にして Linux を 1 MB に CONFIG_TRANSPARENT_HUGEPAGE_MADVISE
を設定 n
まで カーネル構成で。
(2) 上記の構成変更 getconf PAGESIZE
でカーネルを再コンパイルした後 それでも4096を返します。この回答によると CONFIG_HUGETLB_PAGE
CONFIG_HUGETLBFS
経由で取得できるものも必要です .現在再コンパイル中で、再度テストします。
(3) CONFIG_HUGETLBFS
でカーネルを再コンパイルしました 有効になり、現在は /proc/meminfo
対応する 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 に移動しました。ただし、潜在的な副作用についてはわかりません。私の知る限り、私のシステムは問題なく動作しているようです。
引数をいくつかのファイルに入れ、ファイルから「引数」を受け入れるようにプログラムを変更するだけです。一般的な規則 (特に GCC や他のいくつかの GNU プログラムで使用されている) は、 @/tmp/arglist.txt
のような引数は ファイル /tmp/arglist.txt
から引数を読み取るようプログラムに要求します 、多くの場合、引数ごとに 1 行
おそらく長い環境変数を介していくつかのデータを渡すかもしれませんが、それらにも制限があります (そして、カーネルによって制限されるもの 実際には main
のサイズです プログラム引数と環境の両方を含む の初期スタック)
または、引数を介して渡したい情報を含む構成ファイルを介して構成可能になるようにプログラムを変更します。
他の方法では、その制限を回避する方法はありません (execve(2) のマニュアル ページとその 引数と環境のサイズの制限 を参照してください)。 セクション) - スタック制限を上げたら (setrlimit(2) で RLIMIT_STACK
を使用) 、一般的に ulimit
親シェルに組み込まれています)。それ以外の場合は、対処する必要があります。