Apakah Anda menggunakan shell yang sama di kedua percobaan? Mungkin /bin/bashvs. /bin/sh(yang mungkin merupakan tautan ke dasbor)?
maxschlepzig
Ya, saya membuat percobaan dengan 10.000 file dengan nama file yang cukup panjang. "ls *" gagal dan "for f in *" berhasil.
lamwaiman1988
Jawaban:
13
Kesalahan "argumen terlalu panjang" adalah E2BIG, dinaikkan oleh execvepanggilan sistem jika ukuran total argumen (ditambah lingkungan, pada beberapa sistem) terlalu besar. The execvepanggilan adalah salah satu yang dimulai proses eksternal, khususnya loading file executable yang berbeda (ada panggilan yang berbeda, fork, untuk menjalankan proses terpisah yang kode masih dari file eksekusi yang sama). The forLoop adalah shell membangun internal, sehingga tidak melibatkan menelepon execve. Perintah ls *.*memunculkan kesalahan bukan ketika glob diperluas tetapi kapan lsdipanggil.
execvegagal dengan kesalahan E2BIGketika ukuran total argumen ke perintah lebih besar dari ARG_MAXbatas . Anda dapat melihat nilai batas ini pada sistem Anda dengan perintah getconf ARG_MAX. (Mungkin Anda dapat melampaui batas ini jika Anda memiliki cukup memori; menjaga dengan ARG_MAXjaminan yang execveakan berfungsi selama tidak ada kesalahan yang tidak terkait terjadi.)
@ gunbuster363 execveBatasan ini ditegakkan oleh kernel, membatasi batasan karena argumen perlu disalin melalui memori kernel pada satu titik dan proses pengguna tidak dapat diizinkan untuk meminta jumlah memori shell yang sewenang-wenang. Di dalam shell, tidak ada alasan untuk memiliki batasan, apa pun yang sesuai dengan memori virtual baik-baik saja.
Gilles 'SO- stop being evil'
5
Saya kira bahwa dalam contoh pertama lsdijalankan dari bashmelalui fork/ execsistem pasangan panggilan, di satu detik, semua kerja adalah internal untuk bash.
The execpanggilan memiliki batas, kerja internal dari bashbukannya belum (atau lebih baik, memiliki batas yang berbeda yang tidak ada hubungannya dengan exec, mungkin jumlah memori yang tersedia).
Pasti ada batas untuk ekspansi shell. Ini sangat terkait dengan berapa banyak RAM yang Anda miliki .. Coba ini; sistem RAM 4GB saya meniup gasket sekitar 15,2 juta argumen 8-byte:for i in {00000001..20000000} ;do ((10#$i==1)) && break; done
Peter.O
4
@ Fred Saya tidak benar-benar berpikir bahwa menyebutkan RAM sebagai batasan diperlukan.
Šimon Tóth
2
Mungkin tidak diperlukan, tetapi itulah sifat komentar .. seseorang mungkin menganggapnya menarik, atau bahkan bernilai.
Peter.O
@ Fred: sebenarnya ya, jika memperluas argumen yang sangat besar adalah masalah umum, akan mungkin untuk mengimplementasikannya tanpa menyimpan semuanya dalam memori.
/bin/bash
vs./bin/sh
(yang mungkin merupakan tautan ke dasbor)?Jawaban:
Kesalahan "argumen terlalu panjang" adalah
E2BIG
, dinaikkan olehexecve
panggilan sistem jika ukuran total argumen (ditambah lingkungan, pada beberapa sistem) terlalu besar. Theexecve
panggilan adalah salah satu yang dimulai proses eksternal, khususnya loading file executable yang berbeda (ada panggilan yang berbeda,fork
, untuk menjalankan proses terpisah yang kode masih dari file eksekusi yang sama). Thefor
Loop adalah shell membangun internal, sehingga tidak melibatkan meneleponexecve
. Perintahls *.*
memunculkan kesalahan bukan ketika glob diperluas tetapi kapanls
dipanggil.execve
gagal dengan kesalahanE2BIG
ketika ukuran total argumen ke perintah lebih besar dariARG_MAX
batas . Anda dapat melihat nilai batas ini pada sistem Anda dengan perintahgetconf ARG_MAX
. (Mungkin Anda dapat melampaui batas ini jika Anda memiliki cukup memori; menjaga denganARG_MAX
jaminan yangexecve
akan berfungsi selama tidak ada kesalahan yang tidak terkait terjadi.)sumber
execve
Batasan ini ditegakkan oleh kernel, membatasi batasan karena argumen perlu disalin melalui memori kernel pada satu titik dan proses pengguna tidak dapat diizinkan untuk meminta jumlah memori shell yang sewenang-wenang. Di dalam shell, tidak ada alasan untuk memiliki batasan, apa pun yang sesuai dengan memori virtual baik-baik saja.Saya kira bahwa dalam contoh pertama
ls
dijalankan daribash
melaluifork
/exec
sistem pasangan panggilan, di satu detik, semua kerja adalah internal untukbash
.The
exec
panggilan memiliki batas, kerja internal daribash
bukannya belum (atau lebih baik, memiliki batas yang berbeda yang tidak ada hubungannya denganexec
, mungkin jumlah memori yang tersedia).sumber
exec
dalam/usr/include/linux/limits.h
biasanya, didefinisikan sebagaiARG_MAX
.Karena dalam kasus
ls
itu adalah argumen, dan jumlah argumen terbatas.Dalam hal
for
siklus, itu hanya daftar item. Tidak ada batasan (sejauh yang saya ketahui) untuk itu.sumber
for i in {00000001..20000000} ;do ((10#$i==1)) && break; done