GNU/Linux >> Belajar Linux >  >> Linux

Cara mengatasi batas Terlalu Banyak Argumen Linux

sunting:

Akhirnya saya dapat mengirimkan <=256 KB sebagai argumen baris perintah tunggal (lihat edit (4) di bawah). Namun, harap baca dengan cermat bagaimana saya melakukannya dan putuskan sendiri apakah ini jalan yang Anda inginkan. Setidaknya Anda harus bisa memahami mengapa Anda 'macet' jika tidak dari apa yang saya temukan.

Dengan penggabungan ARG_MAX ke ulim -s / 4 muncul pengenalan MAX_ARG_STRLEN sebagai maks. panjang argumen:

/*
 *  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 didefinisikan sebagai 32 kali ukuran halaman dalam 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

...

Ukuran halaman default adalah 4 KB sehingga Anda tidak dapat memberikan argumen lebih dari 128 KB.

Saya tidak dapat mencobanya sekarang, tetapi mungkin beralih ke mode halaman besar (ukuran halaman 4 MB) jika memungkinkan di sistem Anda menyelesaikan masalah ini.

Untuk informasi dan referensi yang lebih mendetail, lihat jawaban ini untuk pertanyaan serupa di Unix &Linux SE.

edit:

(1) Menurut jawaban ini seseorang dapat mengubah ukuran halaman x86_64 Linux menjadi 1 MB dengan mengaktifkan CONFIG_TRANSPARENT_HUGEPAGE dan menyetel CONFIG_TRANSPARENT_HUGEPAGE_MADVISE ke n di konfigurasi kernel.

(2) Setelah mengkompilasi ulang kernel saya dengan perubahan konfigurasi di atas getconf PAGESIZE masih mengembalikan 4096. Menurut jawaban ini CONFIG_HUGETLB_PAGE juga diperlukan yang dapat saya tarik melalui CONFIG_HUGETLBFS . Saya sedang mengkompilasi ulang sekarang dan akan menguji lagi.

(3) Saya mengkompilasi ulang kernel saya dengan CONFIG_HUGETLBFS diaktifkan dan sekarang /proc/meminfo berisi HugePages_* yang sesuai entri yang disebutkan di bagian terkait dari dokumentasi kernel. Namun, ukuran halaman menurut getconf PAGESIZE masih tidak berubah. Jadi sementara saya seharusnya dapat meminta halaman besar melalui mmap panggilan, ukuran halaman default kernel menentukan MAX_ARG_STRLEN masih tetap sebesar 4 KB.

(4) Saya memodifikasi linux/include/uapi/linux/binfmts.h ke #define MAX_ARG_STRLEN (PAGE_SIZE * 64) , mengkompilasi ulang kernel saya dan sekarang kode Anda menghasilkan:

...

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

Jadi sekarang batasnya dipindahkan dari 128 KB ke 256 KB seperti yang diharapkan. Saya tidak tahu tentang potensi efek sampingnya. Sejauh yang saya tahu, sistem saya tampaknya berjalan dengan baik.


Masukkan saja argumen ke dalam beberapa file, dan modifikasi program Anda untuk menerima "argumen" dari file. Konvensi umum (terutama digunakan oleh GCC dan beberapa program GNU lainnya) adalah argumen seperti @/tmp/arglist.txt meminta program Anda untuk membaca argumen dari file /tmp/arglist.txt , seringkali satu baris per argumen

Anda mungkin melewatkan beberapa data melalui variabel lingkungan yang panjang, tetapi data tersebut juga terbatas (dan apa yang dibatasi oleh kernel sebenarnya adalah ukuran main tumpukan awal, berisi argumen program dan lingkungan)

Alternatifnya, modifikasi program Anda agar dapat dikonfigurasi melalui beberapa file konfigurasi yang akan berisi informasi yang ingin Anda sampaikan melalui argumen.

Dengan cara lain, tidak ada cara untuk menghindari batasan itu (lihat halaman manual execve(2) dan Batas ukuran argumen dan lingkungan bagian) - setelah Anda menaikkan batas tumpukan (menggunakan setrlimit(2) dengan RLIMIT_STACK , umumnya dengan ulimit bawaan di Shell induk). Anda harus menghadapinya jika tidak.


Linux
  1. Bagaimana Linux datang ke mainframe

  2. Bagaimana cara mendapatkan jumlah CPU di Linux menggunakan C?

  3. Bagaimana cara mendapatkan nama pengguna di C/C++ di Linux?

  1. Linux – Bagaimana Cara Mendapatkan Nama Sistem Operasi yang Andal?

  2. Linux – Bagaimana Mendapatkan Waktu Jam Dinding Dari Proses Yang Berjalan?

  3. Bagaimana cara mengubah batas waktu habis MySQL di Linux?

  1. Bagaimana saya bisa mendapatkan status keyboard di Linux?

  2. Bagaimana cara mendapatkan jumlah disk fisik di Linux?

  3. Bagaimana cara mendapatkan ukuran fisik file di Linux?