Jika sebuah shell diminta untuk melakukan perintah yang mungkin tidak berguna ( atau sebagian tidak berguna ) yang dikenal untuk mengakhiri, seperti cat hugeregularfile.txt > /dev/null
, bisakah ia mengabaikan eksekusi perintah itu ( atau menjalankan yang lebih murah, katakanlah, touch -a hugeregularfile.txt
)?
Lebih umum, apakah shell mirip dengan kompiler C karena ia dapat melakukan transformasi pada kode sumber, asalkan perilaku yang dapat diamati secara eksternal adalah seolah-olah mesin abstrak mengevaluasinya?
EDIT
Nota Bene: Pertanyaan saya yang semula diajukan memiliki judul yang menanyakan apakah shell diizinkan untuk melakukan optimasi ini, bukan apakah harus atau bahkan apakah implementasi yang dapat melakukannya ada. Saya tertarik pada teori lebih dari praktik, meskipun keduanya diterima.
cat
ting itu membuat perbedaan besar. Shell dapat mengetahui bahwa file tersebut adalah perangkat, tetapi tidak perlu dapat diandalkan.wc
, contohnya). Tapi sepengetahuan saya POSIX tidak mengambil posisi pada optimasi shell; Atau apakah itu?ksh
. Seperti mereka tidak mengatakan proses terpisah tetapi subkulit lingkungan untuk memungkinkan optimasi penghematan garpu.Jawaban:
Tidak, itu ide yang buruk.
cat hugeregularfile.txt > /dev/null
dantouch -a hugeregularfile.txt
tidak sama.cat
akan membaca seluruh file, bahkan jika Anda mengarahkan output ke/dev/null
. Dan membaca seluruh file mungkin persis seperti yang Anda inginkan. Misalnya untuk men-cache-nya sehingga nantinya dibaca akan jauh lebih cepat. Shell tidak bisa mengetahui niat Anda.Demikian pula, kompiler C tidak akan pernah mengoptimalkan membaca file, bahkan jika Anda tidak melihat hal-hal yang Anda baca.
sumber
true
danfalse
) memiliki potensi efek samping, dan efek sampingnya hampir selalu merupakan titik untuk menjalankan perintah. Shell tidak dapat mengetahui efek samping tersebut di muka (untuk program eksternal seperticat
) tanpa menyelesaikan Masalah Berhenti. Jadi itu benar tidak mencoba, dan menganggap Anda berarti apa yang Anda katakan.cat
. Bahkan,cat
bisa melakukan apa saja dari memformat hard drive Anda hingga mengunduh Internet.true
danfalse
atur$?
.cat
dan/dev/null
memiliki arti yang khas tetapi mereka tidak dijamin berperilaku seperti itu. Untuk melakukan optimasi sambil memastikan tidak ada perubahan pada perilaku yang diharapkan, optimasi hanya dapat diizinkan melibatkan konstruksi yang diimplementasikan dalam shell itu sendiri dan bukan hal-hal yang ditemukan di lingkungan eksekusi ... tidak peduli seberapa intuitif nama mereka.Tidak, karena
/dev/null
ini hanya sebuah nama, yang dapat digunakan untuk perangkat lain atau untuk file selain apa yang "biasanya" merupakan tempat penyimpanan data.Jadi shell (atau program lain) tidak tahu, berdasarkan namanya, apakah file yang ditulisnya melakukan sesuatu "nyata" dengan data. Ada AFAIK juga tidak ada sistem panggilan program shell dapat membuat, untuk menentukan bahwa misal file descriptor sebenarnya tidak melakukan apa-apa.
Perbandingan Anda dengan mengoptimalkan kode jauh dalam program C tidak berfungsi, karena shell tidak memiliki tinjauan total yang dimiliki oleh kompiler C terhadap sepotong kode sumber. Shell tidak cukup tahu tentang
/dev/null
cara mengoptimalkan contoh Anda, lebih seperti kompiler C tidak cukup tahu tentang kode dalam suatu fungsi, sebut saja tautannya secara dinamis, untuk tidak melakukan panggilan.sumber
/dev/null
secara khusus, kadang-kadang. Sebuah builtin yang memiliki stdout diarahkan ke/dev/null
, misalnyaecho foo >/dev/null
, tidak akan menghasilkan penulisan yang dilakukan/dev/null
. Itu tidak melakukan sesuatu yang istimewa jika menjalankan perintah non-builtin (seperticat file >/dev/null
).cat
bisa juga menjadi hal lain. Sebenarnya ada yang lain./dev/null
adalah salah satu dari sangat sedikit jalur standar , bersama dengan/dev/tty
,/dev/console
,/tmp
,/dev/
dan/
.cat
adalah ksh93 builtin (tidak diaktifkan kecuali Anda letakkan/opt/ast/bin
sebelumnya/bin
(atau di mana puncat
tersedia)$PATH
). Dan ya, meskipuncat file > /dev/null
dengan builtin ituread
isinyafile
, itu tidak menulisnya ke / dev / null (meskipun terbuka dan fstats itu).Ini tidak akan mengoptimalkan perintah yang sedang berjalan (dan Anda sudah menerima sejumlah jawaban bagus yang mengatakan mengapa tidak), tetapi mungkin mengoptimalkan garpu, pipa / soket, baca dalam beberapa kasus. Jenis optimisasinya:
trap
s telah ditetapkan. Misalnya dalamsh -c ls
, sebagian besarsh
implementasi (bash
,mksh
,ksh
,zsh
,yash
, beberapa versiash
) tidak akan garpu proses untuk menjalankanls
.ksh93
, substitusi perintah tidak akan membuat proses pipa atau garpu sampai perintah eksternal dipanggil ($(echo foo)
misalnya akan meluasfoo
tanpa pipa / soketpair atau garpu).read
built-in beberapa kerang (bash
, AT & Tksh
) tidak akan melakukan single-byte berbunyi jika mereka mendeteksi stdin adalah seekable (dalam hal ini mereka akan melakukan besar membaca dan mencari kembali ke akhir dari apa yang mereka dimaksudkan untuk membaca).sumber
ksh93
adalah shell memimpin di depan optimasi karena tujuannya adalah / harus dilihat setara dengan bahasa pemrograman sepertiperl
. Jadi Anda dapat melihatksh
dokumentasi, kode (semoga sukses) dan milis untuk info lebih lanjut.sh -c 'ps -p "$$"'
yang akan memberi Andaps
dan tidaksh
dengansh
implementasi tersebut, atau dengan strace / truss / tusc ...ksh -c 'ps; ps'
dan bash -c 'ps; ps' menarik. Ksh93 melangkah lebih jauh dalam optimalisasi.ksh
sedang kita bicarakan di sini.mksh
berperilaku sepertibash
. Perilaku itu sebagian besar dimaksudkan untuk mengoptimalkan hal-hal sepertisystem("some command")
. Perhatikan bahwa ada efek samping dari optimasi itu ketika datang ke status keluar dari proses yang diakhiri oleh sinyal (dalam beberapa shell).ksh93
dulu memiliki bug karena melakukan optimasi bahkan ketika jebakan ditetapkan.Saat melihat
cat hugeregularfile.txt > /dev/null
, shell tidak boleh percaya bahwa tindakan itu tidak berguna -cat
bukan bagian dari shell dan bisa melakukan apa pun secara teori, dan juga dalam praktik.Misalnya, pengguna mungkin telah mengganti nama executable
rm
menjadicat
, dan tiba-tiba baris melakukan perilaku yang dapat diamati secara eksternal, yaitu, menghapus file.Pengguna mungkin telah mengompilasi versi
cat
yang masuk ke loop tak terbatas, sehingga shell tidak dapat berasumsi bahwa itu 'diketahui mengakhiri' seperti yang Anda sarankan.Seseorang mungkin telah menginstal versi
cat
yang berfungsi sebagaimana dimaksud, tetapi dengan efek samping tambahan menginstal rootkit jika pernah dijalankan dengan hak istimewa yang memadai - sekali lagi, shell harus menjalankannya dengan sepatutnya.sumber
mksh
memang mengoptimalkanV=$(cat file)
dengan membuatnya builtin. Jadi shell dapat mengoptimalkannya, tetapi tidak mengubahnya menjadi hanyatouch -a
.cat
adalah builtin di dalammksh
, tetapi builtin yang masuk ke sistemcat
jika melewati opsi apa pun, itulah sebabnya dengan GNUcat
,mksh -c 'cat /dev/null --help'
tidak menghasilkan hasil yang sama sepertibash -c 'cat /dev/null --help'
, tetapimksh -c 'cat --help /dev/null'
memberikan Anda sama denganbash -c 'cat --help /dev/null'
(sepertimksh
cat parsing parses pilihan POSIX cara, sedangkan GNU cat mem-parsing mereka dengan cara GNU).V=$(cat file)
dapat dioptimalkan denganV=$(< file)
. Ini mempercepat bahkan tanpa builtincat
.