Borulu komutlar hangi sırayla çalışır?


89

Kabuğun gerçekte borulanmış komutları nasıl yürüttüğünü hiç düşünmedim. Hep "Bir programın stdout'u alır söylendi borulu boru düşünmenin bir yolu olarak, diğerinin stdin içine". Doğal olarak, sanırım, A | B, A önce çalışır, sonra B A'nın stdout'unu alır ve A'nın stdout'unu girdi olarak kullanır.

Ancak, insanlar ps'de belirli bir işlem aradıklarında, komutun sonunda grep'in son çıktıda görünmediğinden emin olmak için grep -v "grep" içerdiklerini farkettim. Bunun anlamı ps aux | grep "bash" | grep -v "grep", yani ps'nin grep'in çalıştığını ve dolayısıyla ps'in çıktısında olduğunu bildiği anlamına gelir. Fakat ps, çıkışı grep'e aktarılmadan önce çalışmayı bitirirse, grep'in çalıştığını nereden biliyordu?

flamingtoast@FTOAST-UBUNTU: ~$ ps | grep ".*"
PID TTY          TIME CMD
3773 pts/0    00:00:00 bash
3784 pts/0    00:00:00 ps
3785 pts/0    00:00:00 grep

neden cevap kabul etmiyorsun ?
törzsmókus

Yanıtlar:


64

Borulu komutlar aynı anda çalışır. Eğer çalıştırdığınızda ps | grep …, o şans beraberlik (veya çekirdek bağırsakları derin zamanlayıcı ince ayar ile kombine kabuk çalışmaları ayrıntıları meselesi) olmadığı konusunda var psya grepilk başlar ve her durumda onlar devam aynı anda yürütmek.

Bu, ilk programın çalışmasını tamamlamadan önce ikinci programın ilk programdan çıkan verileri işlemesine izin vermek için yaygın olarak kullanılır. Örneğin

grep pattern very-large-file | tr a-z A-Z

grepBüyük dosyayı geçmeden önce eşleşen satırları büyük harf olarak göstermeye başlar .

grep pattern very-large-file | head -n 1

ilk eşleşen satırı görüntüler grepve giriş dosyasını okumayı bitirmeden işlemi iyi durdurabilir .

Borulu programların sırayla çalıştığı bir yerde okursanız, bu belgeden kaçın. Borulu programlar aynı anda çalışır ve her zaman vardır.


7
Ve bu örnekte havalı olan şey, kafa ihtiyaç duyduğu bir çizgiyi aldığında, sonlandırır ve grep bunu fark ettiğinde, hiçbir şey için bir sürü iş yapmadan sonlandırır.
Joe

Boruyla ilgili bir tür IO tamponu olduğunu tahmin ediyorum ... bayt cinsinden boyutunu nasıl bilebilirim? Bu konuda daha fazla bilgi edinmek için ne okumak istiyorum? :)
n611x007

3
@ naxa Aslında iki tampon var. Orada stdio içine tampon grepprogramı ve boru kendisinde çekirdek tarafından yönetilen bir tampon var. Sonuncusu için bkz . Boru tamponu ne kadar büyük?
Gilles

49

Komutların çalıştırılma sırası aslında önemli değildir ve garanti edilmez. Ve gizli detayları bir yana pipe(), fork(), dup()ve execve(), kabuk ilk boru, süreçler arasında veri veri kanalını oluşturur ve bunlara bağlı boru uçları ile işlemler yaratır. Çalışan ilk işlem ikinci işlemden girdi beklemesini engelleyebilir veya ikinci işlemin borudan veri okumaya başlamasını bekleyebilir. Bu bekleme keyfi olarak uzun olabilir ve önemli değil. İşlemler hangi sırada yapılırsa yapılsın, veriler sonunda aktarılır ve her şey çalışır.


5
Güzel cevap, ancak OP süreçlerin sırayla yürüdüğünü düşünüyor. Burada işlemlerin eşzamanlı olarak yürütüldüğünü ve borunun benzer olduğunu… suyun kovanlar arasında, aynı zamanda (yaklaşık) aynı anda aktığı yerde daha net hale getirebilirsiniz.
Keith

Açıklama için teşekkürler. Okuduğum kaynaklar, eşzamanlı değil, sıralı dizilmiş programlar gibi göründüğünü gösteriyor.
action_potato

Belirsiz bir şekilde başlayan süreçleri deneyimlemek için bu 1000 defa çalıştırmayı deneyin: echo -na> & 2 | yankı b> & 2
Ole Tange

28

Ölü bir atı atma riski altında, yanlış anlama, öyle görünüyor.

    A | B

eşittir

    A > temporary_file 
    B < temporary_file 
    rm temporary_file

Ancak, Unix oluşturulduğunda ve çocuklar dinozorları okula sürdüğünde, diskler çok küçüktü ve oldukça boş bir komutun dosya sistemindeki tüm boş alanları kullanması yaygındı. BGibi bir şey olsaydı , boru hattının son çıktısı bu ara dosyadan çok daha küçük olabilirdi . Bu nedenle, boru olup için bir kısaltma olarak, geliştirilen “çalıştırmak bir birinci ve çalıştırmak B girişi ile bir ‘in çıkış”modeli, ama için bir yol olarak eş zamanlı olarak çalıştırmak için ve ara dosyasını depolamak için ihtiyacı ortadan kaldırır diskte.grep some_very_obscure_stringBA


2
Bu neden cevaplar ve dolayısıyla oyumu alır.
Küçük Eski Orman Kami

1

Genellikle bunu bash altında çalıştırın. süreç aynı anda çalışır ve çalışır, ancak paralel olarak kabuk tarafından çalıştırılır. Bu nasıl mümkün olaiblir?

  1. Boruda son komut değilse, bir çift soketten oluşan adsız bir boru oluşturun.
  2. çatal
  3. çocukta gerektiğinde soketlere stdin / stdout atayın (boru stdin'deki ilk işlem için yeniden atanmamış, son işlem ve stdout için aynı)
  4. EXEC alt öğesinde, orijinal kabuk kodunu temizleyen, ancak tümü tarafından açılan soketlerin bırakıldığı argümanlarla belirtilen komut. alt süreç kimliği değişmeyecek çünkü bu alt alt işlem aynı
  5. eşzamanlı olarak çocukla fakat ana kabuk altında paralel olarak adım 1'e gidin.

Sistem, yürütmenin ne kadar hızlı yürütüleceğini garanti etmez ve belirtilen komut başlar. kabuktan bağımsız, ama sistem. Bunun nedeni ise:

ps auxww| grep ps | cat

bir kez göster grepve / veya pskomutu ve bir sonraki. Sistem yürütme işlevini kullanarak çekirdeğin işlemlere ne kadar hızlı başladığına bağlıdır.


1
Eşzamanlı yürütme, aynı zaman çerçevesi içinde iki veya daha fazla sürecin, genellikle bunlar arasında bir tür bağımlılıkla yürütüldüğü anlamına gelir. Paralel yürütme, iki veya daha fazla işlemin aynı anda yürütüldüğü anlamına gelir (örneğin, aynı anda ayrı CPU çekirdeğinde). Paralellik soru ile ilgili değildir, "ne kadar hızlı" exec()da yürütülmektedir, ancak exec()bir borudaki programların çağrılması ve yürütülmesi nasıl bir araya getirilir ?
Thomas Nyman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.