Apakah utilitas Linux cerdas ketika menjalankan perintah yang disalurkan?

23

Saya baru saja menjalankan beberapa perintah di terminal dan saya mulai bertanya-tanya, apakah Unix / Linux mengambil jalan pintas saat menjalankan perintah pipa?

Sebagai contoh, katakanlah saya memiliki file dengan satu juta baris, 10 di antaranya berisi hello world. Jika Anda menjalankan perintah grep "hello world" file | headapakah perintah pertama berhenti segera setelah ia menemukan 10 baris, atau apakah ia terus mencari seluruh file terlebih dahulu?

DisgruntledGoat
sumber
2
Itu sebabnya gnu grep punya -margumen.
Paul Tomblin
3
Terminal tidak ada hubungannya dengan itu. Perintah pipa dikelola oleh shell.
Keith Thompson
@KeithThompson maafkan ketidaktahuan saya, saya tidak besar pada terminologi, tidak yakin apakah menyebutnya terminal, shell atau command line. Jangan ragu untuk menyarankan suntingan ke pertanyaan saya :)
DisgruntledGoat

Jawaban:

30

Semacam. Shell tidak tahu perintah apa yang sedang Anda jalankan, ia hanya menghubungkan output dari satu ke input yang lain.

Jika grepmenemukan lebih dari 10 baris yang mengatakan "hello world" maka headakan memiliki semua 10 baris yang diinginkan, dan tutup pipa. Ini akan menyebabkan grepterbunuh dengan SIGPIPE, sehingga tidak perlu melanjutkan pemindaian file yang sangat besar.

psusi
sumber
2
Jadi saya kira, karena kondisi balapan, grep mungkin sudah membaca pola 11 atau 12, tetapi mungkin bukan yang 100 ribu?
pengguna tidak diketahui
3
Ini sebagian tergantung pada panjang garis dan ukuran buffer pipa, tetapi jawaban singkatnya adalah bahwa grep akan membaca sejumlah data ekstra yang cukup terbatas sebelum dibunuh.
dmckee
1
@ penggunaunknown, tepatnya.
psusi
Keren, saya tidak tahu itu terjadi. Saya pikir grepakan terus mengirim output menjadi kosong, mirip dengan/dev/null
Izkata
15

Ketika suatu program mencoba menulis ke sebuah pipa dan tidak ada proses membaca dari pipa itu, maka program penulis menerima sinyal SIGPIPE . Tindakan default ketika sebuah program menerima SIGPIPE adalah untuk menghentikan program. Suatu program dapat memilih untuk mengabaikan sinyal SIGPIPE, dalam hal ini penulisan mengembalikan kesalahan ( EPIPE).

Dalam contoh Anda, inilah garis waktu dari apa yang terjadi:

  • The grepdan headperintah start up secara paralel.
  • grep membaca beberapa input, mulai memprosesnya.
  • Pada titik tertentu, grepmenghasilkan potongan output pertama.
  • head membaca potongan pertama itu dan menulisnya.
  • Dengan asumsi ada garis yang cukup setelah 10 pertandingan pertama (jika tidak grepmungkin berakhir terlebih dahulu), akhirnya headakan dicetak jumlah garis yang diinginkan. Pada titik ini, headkeluar.
  • Tergantung pada kecepatan relatif grepdan headproses, grepmungkin telah mengumpulkan beberapa data dan belum mencetaknya. Pada saat headkeluar, grepmungkin sedang membaca input atau melakukan pemrosesan internal, dalam hal ini akan terus melakukannya.
  • Segera grepakan menulis data yang sedang diproses. Pada saat itu, ia akan menerima SIGPIPE dan mati.

Kemungkinan grepakan memproses sedikit lebih banyak input daripada yang diperlukan, tetapi biasanya hanya beberapa kilobyte:

  • headbiasanya membaca dalam potongan beberapa kilobyte (karena itu lebih efisien daripada mengeluarkan readpanggilan sistem untuk setiap byte - perilaku ini disebut buffering), sehingga sisa potongan terakhir setelah baris terakhir yang diinginkan dibuang.
  • Mungkin ada beberapa data dalam perjalanan, karena pipa memiliki buffer terkait yang dikelola oleh kernel (seringkali 512 byte). Data ini akan dibuang.
  • grepmungkin telah mengakumulasikan beberapa data yang siap menjadi potongan keluaran (buffering lagi). Ini akan menerima SIGPIPE ketika mencoba untuk menyiram buffer outputnya.

Semua dalam semua sistem dirancang dengan tepat sehingga utilitas penyaringan secara alami berperilaku efisien. Program yang perlu terus berjalan ketika saluran output mereka mati harus mengambil langkah mengabaikan sinyal SIGPIPE.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

Sortof, pipeline bekerja seperti ini: pertama mengeksekusi perintah pertama dan kemudian perintah kedua dalam kasus Anda.

Artinya, mari kita A|Bmenjadi perintah yang diberikan. Maka tidak pasti apakah dimulai Aatau tidak B. Mereka mungkin mulai pada waktu yang sama persis jika ada beberapa CPU. Sebuah pipa dapat menampung jumlah data yang tidak ditentukan tetapi terbatas.

Jika B mencoba membaca dari pipa, tetapi tidak ada data yang tersedia, Bakan menunggu sampai data tiba. Jika Bsedang membaca dari disk, Bmungkin memiliki masalah yang sama dan perlu menunggu sampai disk selesai dibaca. Analogi yang lebih dekat adalah membaca dari keyboard. Di sana, Bperlu menunggu pengguna mengetik. Tetapi dalam semua kasus ini, B telah memulai operasi "baca" dan harus menunggu sampai selesai. Tetapi jika Bsuatu perintah sedemikian rupa sehingga hanya membutuhkan sebagian output Akemudian setelah titik tertentu Bdi mana level input tercapai, Aakan dibunuh oleh SIGPIPE

Jika Amencoba menulis ke pipa dan pipa penuh, Aharus menunggu beberapa ruang di pipa menjadi bebas. Abisa memiliki masalah yang sama jika sedang menulis ke terminal. Terminal memiliki kontrol aliran dan dapat memoderasi laju data. Bagaimanapun, untuk A, ia telah memulai operasi "tulis" dan akan menunggu sampai operasi penulisan selesai.

Adan Bberperilaku sebagai proses bersama, meskipun tidak semua proses bersama akan berkomunikasi dengan pipa. Tidak ada yang memegang kendali penuh atas yang lain.

harish.venkat
sumber
1
Pertanyaannya adalah: "apa yang akan dilakukan A ketika B menutup sisi pipa?"
enzotib
2
Bukankah itu 'pipa pecah'?
Patkos Csaba
1
Jika suatu program mencoba membaca / menulis dari / ke pipa tertutup (mis. headKeluar), sinyal SIGPIPE muncul dalam program dan perilaku defaultnya adalah untuk keluar.
Lekensteyn
Bagaimana tepatnya ini menjawab pertanyaan? Tampaknya jawaban psusi lebih pendek dan lebih tepatnya.
jw013
1

greptidak memiliki kontrol langsung terhadap pipa (itu hanya menerima data), dan pipa tidak memiliki kontrol langsung grep(hanya mengirim data) ...

Apa grep, atau program lain apa pun, sepenuhnya tergantung pada logika internal program tersebut. Jika Anda memberi tahu grepmelalui opsi baris perintah untuk membuat keluar awal ketika ditemukan , maka itu akan, jika tidak maka akan terhenti di bagian paling akhir file mencari pola ...

Terminal juga cukup terputus dari cara kerja internal grepdan shelltindakan perpipaan ... Terminal pada dasarnya hanya landasan peluncuran, dan tampilan keluaran ...

Peter.O
sumber