Linux bir süreci nasıl “öldürür”?


91

Genellikle on yıllardır bilgisayarlarla profesyonel olarak çalışıyor olmama rağmen, on yıldan beri Linux ile çalışmam sık sık şaşırtmıyor, aslında işletim sisteminin işlevselliğinin çoğunu sihirden farklı olarak kara kutu olarak görüyorum.

Bugün killemir hakkında düşündüm ve günde birkaç kez kullandığımda (hem "normal" hem de -9lezzetinde) kesinlikle sahne arkasında nasıl çalıştığı hakkında hiçbir fikrim olmadığını itiraf etmeliyim.

Benim bakış açıma göre, çalışan bir süreç "asılı" ise, PID'ini çağırırım killve sonra aniden artık çalışmıyor. Sihirli!

Orada gerçekten ne oluyor? Manpages "sinyaller" hakkında konuşur, ancak bu kesinlikle bir soyutlamadır. kill -9Bir sürece göndermek , sürecin işbirliğini gerektirmez (bir sinyalin işlenmesi gibi), onu öldürür.

  • Linux, işlemin CPU zamanını almaya devam etmesini nasıl önler?
  • Programlamadan kaldırıldı mı?
  • İşlemin açık dosya tanıtıcılarından bağlantısını keser mi?
  • Sürecin sanal belleği nasıl serbest bırakılıyor?
  • Linux, bir işlem tarafından alınan tüm kaynaklara referansları tuttuğu ve bir işlemi "öldürdüğümde", Linux bu tablodan geçer ve kaynakları birer birer serbest bırakır mı?

Gerçekten hepsini bilmek istiyorum!



Yanıtlar:


72

Kill -9'u bir sürece göndermek, sürecin işbirliğini gerektirmez (bir sinyalin kullanımı gibi), sadece onu öldürür.

Bazı sinyallerin yakalanıp göz ardı edilebileceği için hepsinin işbirliği içerdiğini varsayıyorsunuz. Ancak man 2 signal" SIGKILL ve SIGSTOP " sinyalleri yakalanamaz veya göz ardı edilemez ". SIGTERM yakalanabilir, bu nedenle düzlüğün killher zaman etkili olmasının nedeni budur - genellikle işlemin işleyicisindeki bir sorun gider. 1

Bir işlem verilen bir sinyal için bir işleyici tanımlamaz (veya yapamazsa) , çekirdek varsayılan bir eylem gerçekleştirir. SIGTERM ve SIGKILL söz konusu olduğunda bu, işlemi sonlandırmaktır (PID değeri 1 değilse, çekirdek sonlanmaz init) 2 , dosya tanıtıcılarının kapalı olduğu, sistem havuzuna geri döndüğü, ebeveyninin yetimhanesi SIGCHILD'i aldığı anlamına gelir çocukların o aramıştı sadece sanki vb init tarafından devralınan exit(bkz man 2 exit). Süreç artık yok - bir zombi olarak bitmediği sürece, bu durumda çekirdeğin süreç tablosunda hala bazı bilgiler yer alıyor; Bu, ebeveyni olmadığında olurwaitve bu bilgiyi doğru bir şekilde ele alınız. Ancak, zombi işlemlerinde artık kendilerine ayrılan bir bellek yoktur ve bu nedenle yürütülmeye devam edemez.

Linux'un bir işlem tarafından alınan tüm kaynaklara referansları tuttuğu ve bir işlemi "öldürdüğümde" Linux bu tablodan geçtiği ve kaynakları tek tek serbest bıraktığı bellekte global bir tablo gibi bir şey var mı?

Bence bu yeterince doğru. Fiziksel bellek, sayfa tarafından izlenir (genellikle 4 KB'lik bir parçaya eşit bir sayfa) ve bu sayfalar alınır ve genel bir havuza geri döndürülür. Bazı serbest sayfaların, içerdikleri verilerin tekrar gerekli olması durumunda (yani, hala mevcut bir dosyadan okunan veriler) önbelleğe alınması biraz daha karmaşıktır.

Manpages "sinyaller" hakkında konuşur, ancak bu kesinlikle bir soyutlamadır.

Elbette, tüm sinyaller bir soyutlamadır. Kavramsal, tıpkı "süreçler" gibi. Biraz anlamsal oyun oynuyorum, ancak SIGKILL'in SIGTERM'den niteliksel olarak farklı olduğunu düşünüyorsanız, evet ve hayır. Evet, yakalanamadığı anlamında, fakat her ikisi de sinyal olduğu için hayır. Benzetme yapmak gerekirse, bir elma bir portakal değildir, ancak önceden tanımlanmış bir tanımlamaya göre, her iki meyve de elma ve portakaldır. SIGKILL yakalayamadığınız için daha soyut görünüyor , ama yine de bir sinyal. SIGTERM kullanımına bir örnek: Bunları daha önce gördüğünüze eminim:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

void sighandler (int signum, siginfo_t *info, void *context) {
    fprintf (
        stderr,
        "Received %d from pid %u, uid %u.\n",
        info->si_signo,
        info->si_pid,
        info->si_uid
    );
}

int main (void) {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_sigaction = sighandler;
    sa.sa_flags = SA_SIGINFO;
    sigaction(SIGTERM, &sa, NULL);
    while (1) sleep(10);
    return 0;
}

Bu süreç sonsuza kadar uyuyacak. Bir terminalde çalıştırabilir ve SIGTERM ile birlikte gönderebilirsiniz kill. Gibi şeyler tükürür:

Received 15 from pid 25331, uid 1066.

1066 benim kimliğim. PID kill, yürütüldüğü kabuğun kimliği veya eğer çatallamanız durumunda öldürme PID'si olacaktır ( kill 25309 & echo $?).

Yine, SIGKILL için bir işleyici ayarlamanın bir anlamı yoktur çünkü işe yaramaz. 3 Eğer ben kill -9 25309işlem biterse. Ancak bu hala bir sinyaldir; çekirdek, sinyali kimin gönderdiği , ne tür bir sinyal , vb. hakkında bilgi sahibidir .


1. Olası sinyaller listesine bakmadıysanız , bkz kill -l.

2. Tim Post'un da belirttiği diğer bir istisna, kesintisiz uykudaki işlemler için geçerlidir . Bunlar, temel sorun çözülene kadar uyandırılamaz ve bu nedenle ALL sinyalleri (SIGKILL dahil) süresi için ertelenir. Ancak bir süreç bu durumu bilerek oluşturamaz.

3. Bu kullanmanın kill -9pratikte yapılacak daha iyi bir şey olduğu anlamına gelmez . Örnek işleyicim, yol göstermediği anlamda kötü bir şey exit(). Bir SIGTERM işleyicisinin asıl amacı, işleme geçici dosyaları temizleme, sonra gönüllü olarak çıkma gibi şeyler yapma şansı vermek. Eğer kullanırsanız kill -9, bu şans yoktur, bu nedenle sadece "çıkış gönüllü" bölümünün başarısız gibi görünüyor eğer bunu.


Tamam, ama bu süreci neyin öldürdüğü, -9çünkü asıl sorun, bunun kimin ölmesi gerektiğini nasıl hak ettiği! ;)
Kiwy

@Kiwy: Çekirdek. Sinyalleri içeren IPC içinden geçer; çekirdek varsayılan eylemleri uygular.
goldilocks

12
İşlem bu durumda iken disk uykusunun (D) tüm sinyalleri önlediğinden bahsetmeye değer olabilir. Bu nedenle, kill -9belirli G / Ç'ye bağlı işlemlere çalışmak, en azından hemen çalışmaz.
Tim Post

7
Bir kill -9yakalanamadığı için, onu alan bir işlemin çıkmadan önce herhangi bir temizleme işlemi (örn. Geçici dosyaları kaldırmak, paylaşılan hafızayı boşaltmak vb.) Yapamayacağını eklerdim. Bu nedenle, kill -9(aka kill -kill) yalnızca son çare olarak kullanın. Bir başlayın kill -hupve / veya kill -termbirinci ve sonra kullanmak kill -killson darbe olarak.
JRFerguson

"Süreç artık mevcut değil - bir zombi olarak bitmediği sürece, bu durumda çekirdeğin işlem tablosunda bir miktar bilgiyle listeleniyor" aslında, tüm işlemler öldüklerinde zombi durumuna geçer ve zombi kaybolduğunda kaybolur Ebeveyn çocuk için beklemez, normalde bunun gerçekleşmesi için çok hızlı olur
zeki

3

Her işlem planlanan süre boyunca çalışır ve ardından diğer görevler için CPU çekirdeğini vermek üzere donanım zamanlayıcısı tarafından durdurulur. Bu yüzden CPU çekirdeğinden daha fazla işlem yapabilmek ya da tek bir çekirdekli işlemcide çok fazla işlemle tüm işletim sistemlerini çalıştırmak bile mümkün.

İşlem kesildikten sonra kontrol, çekirdek koduna döner. Bu kod daha sonra, kesilen sürecin yürütülmesine devam edilmemesi, işlem tarafından herhangi bir işbirliği yapılmadan bir karar verebilir. kill -9, programınızın herhangi bir satırında çalıştırma ile sonuçlanabilir.


0

Bir sürecin nasıl öldürüldüğünün idealize edilmiş bir açıklaması. Uygulamada, herhangi bir Unix varyantı birçok ek komplikasyona ve optimizasyona sahip olacaktır.

Çekirdek, hangi belleğin eşlendiği, hangi iş parçacıklarının olduğu ve ne zaman programlandığı, hangi dosyaların açıldığı, vs. hakkında bilgi depolayan her işlem için bir veri yapısına sahiptir. Çekirdek bir işlemi öldürmeye karar verirse, işlemin veri yapısı (ve belki de iş parçacıklarının her birinin veri yapısında) işlemin öldürülmesi.

İşlemin iş parçacıklarından biri şu anda başka bir CPU'da zamanlanmışsa, çekirdek bu iş parçacığının daha hızlı çalışmasını durdurmak için diğer CPU'da bir kesmeyi tetikleyebilir.

Zamanlayıcı, bir iş parçacığının öldürülmesi gereken bir süreç içinde olduğunu fark ettiğinde, artık programlamayacaktır.

İşlemin hiçbir iş parçacığı artık programlanmadığında, çekirdek işlemin kaynaklarını serbest bırakmaya başlar (bellek, dosya tanımlayıcıları,…). Çekirdek bir kaynağı serbest bıraktığında, sahibinin hala canlı kaynakları olup olmadığını kontrol eder. İşlem artık canlı kaynağa sahip olmadığında (bellek eşleme, açık dosya tanımlayıcısı,…), işlemin veri yapısı serbest bırakılabilir ve karşılık gelen giriş işlem tablosundan kaldırılabilir.

Bazı kaynaklar derhal serbest bırakılabilir (örn. Bir G / Ç işlemi tarafından kullanılmayan hafızanın serbest bırakılması). Diğer kaynaklar beklemelidir; örneğin, bir G / Ç işlemi açıklayan veriler, G / Ç işlemi devam ederken serbest bırakılamaz (bir DMA devam ederken , erişmekte olduğu hafızanın kullanımda olması ve DMA'nın iptal edilmesi gerekir) çevre birimiyle temas kurma). Böyle bir kaynak için sürücüye bildirimde bulunulur ve iptali için acele etmeye çalışabilir; işlem artık devam etmiyorsa, sürücü bu kaynağın serbest bırakılmasını tamamlar.

(İşlem tablosuna giriş aslında, işlem öldüğünde ve ana olayı kabul ettiğinde serbest kalan ana işleme ait olan bir kaynaktı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.