GNU/Linux >> Linux の 問題 >  >> Linux

Linux の引数が多すぎる制限を回避する方法

編集:

最終的に <=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 親シェルに組み込まれています)。それ以外の場合は、対処する必要があります。


Linux
  1. Linux –オペレーティングシステムの名前を確実に取得するにはどうすればよいですか?

  2. Linux:システムからすべてのログインログを取得する方法は?

  3. LinuxでMySQLのタイムアウト制限を変更するにはどうすればよいですか?

  1. Cを使用してLinuxでCPUの数を取得するには?

  2. Linux の C/C++ でユーザー名を取得するには?

  3. Linux で物理ディスクの数を取得するには?

  1. Linuxがメインフレームに登場した経緯

  2. Linux –実行中のプロセスの壁掛け時計の時間を取得する方法は?

  3. Linuxでキーボードの状態を取得するにはどうすればよいですか?