Linux İşlem Durumları


90

Linux'ta, bir diskten blokları okuması gerektiğinde bir işlemin durumuna ne olur? Engellendi mi? Öyleyse, yürütülecek başka bir süreç nasıl seçilir?

Yanıtlar:


88

Bir dosya tanımlayıcının dönüşünü beklerken read()veya write()geri dönerken, işlem "D" veya "Disk Uykusu" olarak bilinen özel bir uyku türüne konur. Bu özeldir, çünkü böyle bir durumdayken süreç durdurulamaz veya kesintiye uğratılamaz. İoctl () 'den dönüşü bekleyen bir işlem de bu şekilde uykuya alınır.

Bunun bir istisnası, bir dosyanın (bir terminal veya başka bir karakter aygıtı gibi) O_NONBLOCKmodda açıldığında , bir aygıtın (bir modem gibi) başlatılması için zamana ihtiyaç duyacağı varsayıldığında geçmesidir. Ancak sorunuzda cihazları engellemeyi belirttiniz. Ayrıca, ioctl()engellemesiz modda açılan bir fd'de engelleme olasılığı olan bir şeyi hiç denemedim (en azından bilerek değil).

Başka bir sürecin nasıl seçileceği, tamamen kullandığınız zamanlayıcıya ve diğer işlemlerin ağırlıklarını o zamanlayıcı içinde değiştirmek için neler yapmış olabileceğine bağlıdır.

Belirli koşullar altındaki bazı kullanıcı alanı programlarının, yeniden başlatılıncaya kadar sonsuza kadar bu durumda kaldığı bilinmektedir. Bunlar tipik olarak diğer "zombiler" ile gruplandırılır, ancak teknik olarak geçersiz olmadıkları için terim doğru olmaz.


1
"İoctl () 'den dönüş bekleyen bir işlem de bu şekilde uyku moduna geçirilir." Engelleyen bir IOCTL'yi bekleyen kullanıcı alanı sürecimi öldürdüm, bu yüzden bu doğru değil. Anlamadığım sürece
Hamzahfrq

Böyle bir testi zamanlamak çok zor olurdu . Kesintisiz süreçler yok edilemez; onu öldürebildiyseniz, o zaman basitçe engelliyordu (çekirdek, ioctl'nin herhangi bir bölümünün ortasında değildi ve geçtiğiniz konumdaki kullanıcı alanına karşılık gelen herhangi bir yanıtı kopyaladı (veya en azından kopyalamanın ortası)). Linux da bunun yazıldığı 2009 yılından beri çok değişti ; fenomen bir zamanlar olduğu gibi çok daha az gözlemlenebilir.
Tim Post

133

Bir işlemin bir diskten veri alması gerektiğinde, işlemin tamamlanması uzun zaman alabileceği için diğer işlemlerin çalışmasına izin vermek için CPU üzerinde çalışmayı etkin bir şekilde durdurur - bir disk için en az 5 ms arama süresi yaygındır ve 5 ms 10 milyondur CPU döngüleri, program açısından sonsuzluk!

Programcı bakış açısından ("kullanıcı alanında" da denir), buna engelleme sistem çağrısı denir . Eğer ararsanız write(2)(aynı isimli sistem çağrısı etrafında ince libc sarıcı olan), sizin süreç tam o sınır durmaz; çekirdekte sistem çağrı kodunu çalıştırmaya devam eder. Çoğu zaman belirli bir disk denetleyici sürücüsüne kadar gider (dosya adı → dosya sistemi / VFS → blok aygıtı → aygıt sürücüsü), burada diskteki bir bloğu getirme komutunun uygun donanıma gönderildiği çok önemlidir. çoğu zaman hızlı işlem.

SONRA süreç uyku durumuna alınır (çekirdek alanında engellemeye uyku denir - çekirdek açısından hiçbir şey 'engellenmez'). Donanım nihayet uygun veriyi aldıktan sonra uyandırılacak, ardından işlem çalıştırılabilir olarak işaretlenecek ve planlanacaktır. Sonunda, planlayıcı işlemi çalıştıracaktır.

Son olarak, kullanıcı alanında, engelleyen sistem çağrısı uygun durum ve verilerle geri döner ve program akışı devam eder.

Çoğu G / Ç sistem çağrısını engellemesiz modda çağırmak mümkündür (bkz O_NONBLOCK. open(2)Ve içinde fcntl(2)). Bu durumda, sistem çağrıları hemen geri döner ve sadece disk işlemini göndererek rapor verir. Programcı daha sonra işlemin başarılı olup olmadığını açıkça kontrol etmeli ve sonucunu (örn select(2). İle) almalıdır . Buna eşzamansız veya olay tabanlı programlama denir.

D durumundan bahseden ( TASK_UNINTERRUPTIBLELinux durum adlarında anılan ) buradaki yanıtların çoğu yanlıştır. D devlet sadece bu kod yolu bir çekirdek alan kodu yolu tetiklenir özel uyku modu olduğunu kesilemez çok sadece engelleyeceğini de beklentisi ile (o programa çok karmaşık olacağından), kısa zaman. Çoğu "D durumunun" aslında görünmez olduğuna inanıyorum; çok kısa ömürlüdürler ve 'top' gibi örnekleme araçlarıyla gözlenemezler.

D durumunda birkaç durumda öldürülemez süreçlerle karşılaşabilirsiniz. NFS bununla ünlü ve ben birçok kez karşılaştım. Her zaman yerel disklere ve hızlı hata tespiti (SATA'da bir hata zaman aşımı yaklaşık birkaç 100 ms olacaktır) ile her zaman yerel disklere ulaştığını varsayan bazı VFS kod yolları ile gerçekte ağdan veri alan NFS arasında anlamsal bir çatışma olduğunu düşünüyorum. daha esnektir ve yavaş iyileşme gösterir (300 saniyelik bir TCP zaman aşımı yaygındır). Durumla Linux 2.6.25'te sunulan harika çözüm için bu makaleyi okuyun TASK_KILLABLE. Bu çağdan önce, çekirdek iş parçacığına bir SIGKILL göndererek NFS işlem istemcilere sinyal gönderebileceğiniz rpciod, ancak bu çirkin numarayı unuttuğunuz bir hack vardı . ...


2
Ayrıntılı yanıt için +1, ancak bu ileti dizisinin yaklaşık iki yıldır kabul edilen bir yanıtı olduğunu lütfen unutmayın. Daha yeni sorulara yardımcı olmak istiyorsanız "Sorular" bağlantısına tıklayın. Stack Overflow'a hoş geldiniz ve katkıda bulunduğunuz için teşekkürler!
GargantuChet

20
Bu cevap, bazı ortamlarda D durumundaki süreçler için en yaygın açıklama olan NFS'den söz eden tek cevaptır. +1.
Pinko

14
Çok güzel cevap, teşekkürler. Ayrıca, işlemin, değiştirilen sayfaları beklerken D durumuna geçtiğini unutmayın, bu nedenle bir atma işlemi uzun süre D durumunda kalacaktır.
cha0site

@zerodeux iyi cevap, ancak şemanızın (dosya adı -> dosya sistemi / VFS -> cihazı engelle -> cihaz sürücüsü) olması gerektiğini düşünüyorum (dosya adı -> VFS -> dosya sistemi (ext3) -> cihazı engelle -> cihaz sürücüsü)
c4f4t0r

1
Çekirdekte, spinlock'ları bekleyen (disk i / o ile ilgili olabilir veya olmayabilir) tümünün D-durumu olarak rapor edildiğini varsaymak güvenli /proc/statmidir?
fitil

8

G / Ç gerçekleştiren bir işlem , CPU'ya programı yürütmeye geri dönmesini söyleyen bir donanım kesintisi olana kadar CPU'yu serbest bırakan D durumuna (kesintisiz uyku) konulacaktır . man psDiğer işlem durumları için bakın .

Çekirdeğinize bağlı olarak, yürütülmeye hazır bir süreç akışını izleyen bir süreç planlayıcı vardır . Bir zamanlama algoritmasıyla birlikte çekirdeğe hangi işlemin hangi CPU'ya atanacağını söyler. Dikkate alınması gereken çekirdek süreçleri ve kullanıcı süreçleri vardır. Her işleme, kullanmasına izin verilen CPU zamanının bir parçası olan bir zaman dilimi tahsis edilir. Süreç tüm zaman dilimini kullandığında, süresi dolmuş olarak işaretlenir ve programlama algoritmasında daha düşük öncelik verilir.

In 2.6 çekirdeği , bir var O (1) zaman karmaşıklığı zamanlayıcısı çalıştırmakta kadar kaç süreçler, bu sabit zamanda CPU atar bu nedenle olursa olsun,. 2.6'da ön hazırlık ve CPU yük dengeleme getirdiği için bu daha karmaşıktır. Her durumda, verimlidir ve siz G / Ç'yi beklerken CPU'lar boşta kalmayacaktır.


3

Başkaları tarafından daha önce açıklandığı gibi, "D" durumundaki (kesintisiz uyku) işlemler, ps işleminin askıda kalmasından sorumludur. Bana RedHat 6.x ve otomatik olarak bağlanmış NFS ev dizinleri ile birçok kez oldu.

İşlemleri D durumunda listelemek için aşağıdaki komutları kullanabilirsiniz:

cd /proc
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D

İşlemin geçerli dizinini ve sorunlu takılı NFS diskini öğrenmek için aşağıdaki örneğe benzer bir komut kullanabilirsiniz (31134'ü uyku işlem numarasıyla değiştirin):

# ls -l /proc/31134/cwd
lrwxrwxrwx 1 pippo users 0 Aug  2 16:25 /proc/31134/cwd -> /auto/pippo

İlgili bağlanmış nfs dosya sistemine -f (kuvvet) anahtarıyla umount komutunu vermenin uyku sürecini uyandırdığını buldum:

umount -f /auto/pippo

dosya sistemi meşgul olduğu için kaldırılmadı, ancak ilgili işlem uyandı ve sorunu yeniden başlatmadan çözebildim.


1

İşleminizin tek bir iş parçacığı olduğunu ve G / Ç'yi bloke ettiğinizi varsayarsak, işleminiz G / Ç'nin tamamlanmasını beklemeyi engeller. Çekirdek, aynı zamanda kaliteye, önceliğe, son çalıştırma süresine vb. Dayalı olarak çalışacak başka bir işlem seçecektir. Çalıştırılabilir başka süreç yoksa, çekirdek herhangi bir işlem yapmayacaktır; bunun yerine donanıma makinenin boşta olduğunu söyler (bu da daha düşük güç tüketimine neden olur).

G / Ç'nin tamamlanmasını bekleyen işlemler tipik olarak D durumunda, örn., psVe top.


Toplam belleğin yaklaşık% 10'unu kullanarak birkaç işlem başlattım. Birçoğunun D durumunda olduğunu fark ettim. Bu, bu makinedeki yavaş IO'dan mı kaynaklanıyor? Diyelim ki 9 işlemim var, bunlar IO için rekabet ediyor olabilir ve çoğu D durumunda.
Kemin Zhou

@KeminZhou CPU hızlarıyla karşılaştırıldığında, G / Ç oldukça yavaş, hatta hızlı G / Ç. Tek bir I / O ağır işlem, bir manyetik diski, bir SSD'yi bile kolayca meşgul edebilir. 10 I / O ağır işlemler epeyce meşgul olabilir.
derobert

1

Evet, görev read () sistem çağrısında engellenir. Hazır olan başka bir görev çalışır veya başka hiçbir görev hazır değilse, boş görev (o CPU için) çalışır.

Normal, bloke edici bir disk okuması, görevin "D" durumuna girmesine neden olur (diğerlerinin de belirttiği gibi). Bu tür görevler, CPU'yu tüketmeseler bile yük ortalamasına katkıda bulunur.

Bazı diğer IO türleri, özellikle tty'ler ve ağ, tamamen aynı şekilde davranmaz - işlem "S" durumunda sona erer ve kesintiye uğrayabilir ve yük ortalamasına göre sayılmaz.



0

Genellikle süreç engellenir. Okuma işlemi, engellemesiz olarak işaretlenmiş bir dosya tanımlayıcı üzerindeyse veya süreç eşzamansız GÇ kullanıyorsa, engellenmez. Ayrıca, işlemin engellenmemiş başka iş parçacıkları varsa, çalışmaya devam edebilirler.

Bundan sonra hangi sürecin çalışacağına ilişkin karar , çekirdekteki zamanlayıcıya bağlıdır .

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.