SIGINT, SIGTERM, SIGQUIT ve SIGKILL gibi diğer sonlandırma sinyalleriyle nasıl ilişkilidir?


103

POSIX sistemlerinde, sonlandırma sinyalleri genellikle aşağıdaki sıraya sahiptir (birçok MAN sayfasına ve POSIX Spesifikasyonuna göre):

  1. SIGTERM - kibarca bir sürecin sonlandırılmasını isteyin. Tüm kaynakları (dosyalar, soketler, alt işlemler, vb.) Temizleyerek, geçici dosyaları silerek vb. Nazikçe sona erdirilecektir.

  2. SIGQUIT - daha güçlü istek. Dikkatsizce sonlandıracak, yine de kesinlikle temizlenmesi gereken kaynakları temizleyecek, ancak geçici dosyaları silemeyecek, belki bir yere hata ayıklama bilgisi yazacaktır; bazı sistemlerde de bir çekirdek dökümü yazılacaktır (sinyalin uygulama tarafından yakalanmasına bakılmaksızın).

  3. SIGKILL - en güçlü istek. İşlemden bir şey yapması bile istenmez, ancak sistem, istese de istemese de süreci temizleyecektir. Büyük olasılıkla bir çekirdek dökümü yazılmıştır.

SIGINT bu resme nasıl uyuyor? Bir CLI işlemi genellikle kullanıcı CRTL + C'ye ulaştığında SIGINT tarafından sonlandırılır, ancak bir arka plan işlemi de KILL yardımcı programı kullanılarak SIGINT tarafından sonlandırılabilir. Spesifikasyonlarda veya başlık dosyalarında göremediğim şey, SIGINT'in SIGTERM'den daha fazla veya daha az güçlü olması veya SIGINT ile SIGTERM arasında herhangi bir fark olup olmadığıdır.

GÜNCELLEME:

Şimdiye kadar bulduğum sonlandırma sinyallerinin en iyi açıklaması GNU LibC Dokümantasyonunda . SIGTERM ve SIGQUIT arasında amaçlanan bir fark olduğunu çok iyi açıklıyor.

SIGTERM hakkında şöyle diyor:

Bir programın kibarca sonlandırılmasını istemenin normal yolu budur.

Ve SIGQUIT hakkında yazıyor:

[...] ve süreci sonlandırdığında, tıpkı bir program hatası sinyali gibi bir çekirdek dökümü üretir. Bunu, kullanıcı tarafından "tespit edilen" bir program hatası durumu olarak düşünebilirsiniz. [...] Bazı temizleme türleri en iyi SIGQUIT'in işlenmesinde ihmal edilir. Örneğin, program geçici dosyalar oluşturuyorsa, diğer sonlandırma isteklerini geçici dosyaları silerek işlemelidir. Ancak SIGQUIT'in bunları silmemesi daha iyidir, böylece kullanıcı bunları çekirdek dökümü ile bağlantılı olarak inceleyebilir.

Ve SIGHUP da yeterince iyi açıklanıyor. SIGHUP gerçekten bir sonlandırma sinyali değildir, yalnızca kullanıcıya "bağlantının" kesildiği anlamına gelir, bu nedenle uygulama kullanıcının daha fazla çıktı (örn. Stdout / stderr çıkışı) okumasını bekleyemez ve artık kullanıcı. Çoğu uygulama için, bu, çıkmanın daha iyi olacağı anlamına gelir. Teoride bir uygulama, bir SIGHUP alındığında ve şimdi bir arka plan işlemi olarak çalışarak çıktıyı yapılandırılmış bir günlük dosyasına yazarak arka plan programı moduna geçmesine de karar verebilir. Zaten arka planda çalışan çoğu arka plan programı için, SIGHUP genellikle yapılandırma dosyalarını yeniden inceleyecekleri anlamına gelir, böylece yapılandırma dosyalarını düzenledikten sonra arka plan işlemlerine gönderirsiniz.

Ancak bu sayfada, CRTL + C ile gönderilmesi dışında SIGINT'in yararlı bir açıklaması yoktur. SIGINT'i SIGTERM'den farklı bir şekilde ele almanın herhangi bir nedeni var mı? Eğer öyleyse, bu hangi sebep olabilir ve idare nasıl farklı olur?


1
İyi soru. Bazı tarihi Unix kazalarının cevaba dahil olacağından şüpheleniyorum.
Alex B

Bu sorunun eski olduğunu biliyorum, ancak herhangi birinin (Linux) işletim sisteminiz için kapsamlı bir sinyal listesi için buraya gelmesi durumunda sudo fuser -l, komut isteminize yazarak bulunabilir . Benim için bu HUP INT QUIT ILL TRAP ABRT IOT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS UNUSED
Nick Bull

3
Ayrıca kill -lbir sinyal listesi de deneyin .
AAAfarmclub

Yanıtlar:


89

SIGTERM ve SIGKILL, genel amaçlı "bu işlemi sonlandırma" talepleri için tasarlanmıştır. SIGTERM (varsayılan olarak) ve SIGKILL (her zaman) işlemin sonlandırılmasına neden olur. SIGTERM süreç tarafından yakalanabilir (örneğin, isterse kendi temizliğini yapabilmesi için) veya hatta tamamen görmezden gelinebilir; ancak SIGKILL yakalanamaz veya göz ardı edilemez.

SIGINT ve SIGQUIT, özellikle terminalden gelen istekler için tasarlanmıştır: Bu sinyalleri üretmek için belirli giriş karakterleri atanabilir (terminal kontrol ayarlarına bağlı olarak). SIGINT için varsayılan eylem, SIGTERM için varsayılan eylem ve SIGKILL için değiştirilemez eylemle aynı türden süreç sonlandırmadır; SIGQUIT için varsayılan eylem aynı zamanda işlemin sonlandırılmasıdır, ancak bir çekirdek dökümün oluşturulması gibi ek uygulama tanımlı eylemler ortaya çıkabilir. Gerekirse işlem tarafından yakalanabilir veya göz ardı edilebilir.

SIGHUP, sizin de söylediğiniz gibi, bir sonlandırma sinyali olmaktan çok, terminal bağlantısının kaybolduğunu göstermeyi amaçlamaktadır. Ancak yine, SIGHUP için varsayılan eylem (eğer süreç onu yakalamazsa veya yok saymazsa), SIGTERM vb. İle aynı şekilde süreci sonlandırmaktır.

POSIX tanımlarında signal.h, çeşitli sinyalleri ve bunların varsayılan eylemlerini ve amaçlarını listeleyen bir tablo vardır ve Genel Terminal Arayüzü bölümü, terminalle ilgili sinyaller hakkında çok daha fazla ayrıntı içerir.


10
Kilit nokta şudur: SIGINT ve SIGQUIT, program çalışırken terminalden tek karakterler kullanılarak üretilebilir. Diğer sinyaller başka bir program tarafından bir şekilde üretilmelidir (örn. Kill komutu ile). SIGINT, SIGQUIT'ten daha az şiddetlidir; ikincisi bir çekirdek dökümü oluşturur. SIGKILL yakalanamaz. Bağlantınız kesilirse (pencere kapanır, vb.) SIGHUP oluşturulur. Yani hepsinin farklı anlamları var.
Jonathan Leffler

TTY Demystified , sinyallerin çekirdeğin tty alt sistemi ile nasıl etkileşime girdiğine dair kolayca anlaşılabilir bazı bilgilere sahiptir. Cevabınıza biraz bağlam katar.
Daniel Näslund

2
Spesifikasyonlar çok kesin değil gibi görünüyor, ancak benim anladığım kadarıyla SIgint programdan mevcut eylemini durdurmasını istiyor, mutlaka çıkması gerekmiyor. Tasarlanan bir program için, çıkış anlamına gelen her çalıştırma için yalnızca bir eylem gerçekleştirin, ancak bir tür oku-değerlendir-yazdır döngüsüne sahip etkileşimli bir program için bu, mevcut değerlendirmeden vazgeçmek ve kullanıcı girdisini okumaya geri dönmek anlamına gelebilir. Sanırım bunu sigint için daha az yapıyor.
bdsl

Yeniden başlatma sırasında hangi sinyal gönderilir?
Dan Dascalescu

10

DarkDust'un belirttiği gibi birçok sinyal aynı sonuçlara sahiptir, ancak süreçler her sinyalin nasıl üretildiğini ayırt ederek bunlara farklı eylemler ekleyebilir. FreeBSD çekirdek kaynak koduna (kern_sig.c) baktığımda, iki sinyalin de aynı şekilde işlendiğini, süreci sonlandırdığını ve herhangi bir iş parçacığına teslim edildiğini görüyorum.

SA_KILL|SA_PROC,             /* SIGINT */
SA_KILL|SA_PROC,             /* SIGTERM */

9

man 7 signal

Bu, Linux kılavuz sayfaları projesinin uygun, normatif olmayan kılavuz sayfasıdır. Linux sinyal bilgisi için sık sık bakmak isteyeceğiniz .

Sürüm 3.22, aşağıdaki gibi ilginç şeylerden bahseder:

SIGKILL ve SIGSTOP sinyalleri yakalanamaz, engellenemez veya göz ardı edilemez.

ve tabloyu içerir:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process
SIGINT        2       Term    Interrupt from keyboard
SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction
SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal
SIGSEGV      11       Core    Invalid memory reference
SIGPIPE      13       Term    Broken pipe: write to pipe with no
                              readers
SIGALRM      14       Term    Timer signal from alarm(2)
SIGTERM      15       Term    Termination signal
SIGUSR1   30,10,16    Term    User-defined signal 1
SIGUSR2   31,12,17    Term    User-defined signal 2
SIGCHLD   20,17,18    Ign     Child stopped or terminated
SIGCONT   19,18,25    Cont    Continue if stopped
SIGSTOP   17,19,23    Stop    Stop process
SIGTSTP   18,20,24    Stop    Stop typed at tty
SIGTTIN   21,21,26    Stop    tty input for background process
SIGTTOU   22,22,27    Stop    tty output for background process

ActionSIGQUIT'in eylemi olduğu için SIGQUIT'i SIGQUIT'ten ayıran sinyali özetleyenCore veTerm .

Eylemler aynı belgede belgelenmiştir:

The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:

Term   Default action is to terminate the process.

Ign    Default action is to ignore the signal.
Core   Default action is to terminate the process and dump core (see core(5)).
Stop   Default action is to stop the process.
Cont   Default action is to continue the process if it is currently stopped.

Çekirdeğin bakış açısından SIGTERM ve SIGINT arasında herhangi bir fark göremiyorum çünkü ikisinin de eylemi var Termve her ikisi de yakalanabilir. Görünüşe göre bu sadece bir "genel kullanım geleneği farkı":

  • SIGINT, terminalden CTRL-C yaptığınızda olan şeydir
  • SIGTERM, tarafından gönderilen varsayılan sinyaldir kill

Bazı sinyaller ANSI C'dir ve diğerleri değildir

Önemli bir fark şudur:

  • SIGINT ve SIGTERM ANSI C'dir, bu nedenle daha taşınabilir
  • SIGQUIT ve SIGKILL,

C99 taslağı N1256'nın "7.14 Sinyal işleme" bölümünde açıklanmıştır :

  • SIGINT etkileşimli dikkat sinyalinin alınması
  • SIGTERM, programa gönderilen bir fesih isteği

bu da SIGINT'i etkileşimli Ctrl + C için iyi bir aday yapar.

POSIX 7

POSIX 7, sinyalleri şu signal.hbaşlık ile belgeler : https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

Bu sayfada, daha önce gördüğümüz bazı şeylerden bahseden aşağıdaki ilgi tablosu da vardır man 7 signal:

Signal    Default Action   Description
SIGABRT   A                Process abort signal.
SIGALRM   T                Alarm clock.
SIGBUS    A                Access to an undefined portion of a memory object.
SIGCHLD   I                Child process terminated, stopped,
SIGCONT   C                Continue executing, if stopped.
SIGFPE    A                Erroneous arithmetic operation.
SIGHUP    T                Hangup.
SIGILL    A                Illegal instruction.
SIGINT    T                Terminal interrupt signal.
SIGKILL   T                Kill (cannot be caught or ignored).
SIGPIPE   T                Write on a pipe with no one to read it.
SIGQUIT   A                Terminal quit signal.
SIGSEGV   A                Invalid memory reference.
SIGSTOP   S                Stop executing (cannot be caught or ignored).
SIGTERM   T                Termination signal.
SIGTSTP   S                Terminal stop signal.
SIGTTIN   S                Background process attempting read.
SIGTTOU   S                Background process attempting write.
SIGUSR1   T                User-defined signal 1.
SIGUSR2   T                User-defined signal 2.
SIGTRAP   A                Trace/breakpoint trap.
SIGURG    I                High bandwidth data is available at a socket.
SIGXCPU   A                CPU time limit exceeded.
SIGXFSZ   A                File size limit exceeded.

BusyBox başlatma

BusyBox'ın 1.29.2 varsayılan rebootkomutu süreçlere bir SIGTERM gönderir, bir saniye uyur ve ardından SIGKILL gönderir. Bu, farklı dağıtımlarda ortak bir sözleşme gibi görünüyor.

BusyBox sistemini aşağıdakilerle kapattığınızda:

reboot

başlatma sürecine bir sinyal gönderir.

Ardından, başlatma sinyal işleyicisi şu çağrıyı sonlandırır:

static void run_shutdown_and_kill_processes(void)
{
    /* Run everything to be run at "shutdown".  This is done _prior_
     * to killing everything, in case people wish to use scripts to
     * shut things down gracefully... */
    run_actions(SHUTDOWN);

    message(L_CONSOLE | L_LOG, "The system is going down NOW!");

    /* Send signals to every process _except_ pid 1 */
    kill(-1, SIGTERM);
    message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
    sync();
    sleep(1);

    kill(-1, SIGKILL);
    message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
    sync();
    /*sleep(1); - callers take care about making a pause */
}

terminale yazdırır:

The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes

İşte bunun asgari somut bir örneği .

Çekirdek tarafından gönderilen sinyaller


8

Sigint ve sigterm için hızlı bir Google aramasından sonra , ikisi arasındaki amaçlanan tek fark, bir klavye kısayoluyla mı yoksa açık bir çağrı ile mi başlatıldığıdır kill.

Sonuç olarak, örneğin, büyük olasılıkla bir klavye kısayoluyla gönderildiğini bilerek, sigint'i durdurabilir ve onunla özel bir şey yapabilirsiniz. Ölmek yerine ekranı veya başka bir şeyi yenileyin (insanların beklediği gibi önerilmez)^C programı sonlandırmayı için , sadece bir örnek).

Ayrıca ^\kendim kullanmaya başlayabileceğim sigquit göndermesi gerektiğini de öğrendim . Çok kullanışlı görünüyor.


3

kill(Hem sistem çağrısını hem de yardımcı programı ` kullanarak , izniniz olduğu takdirde herhangi bir işleme hemen hemen her sinyali gönderebilirsiniz. Bir süreç, bir sinyalin nasıl canlandığını ve onu kimin gönderdiğini ayırt edemez.

Bununla birlikte, SIGINT gerçekten Ctrl-C kesintisini belirtmek içindir, SIGTERM ise genel terminal sinyalidir. Engellenemeyen veya işlenemeyen sinyaller (man sayfasına göre SIGKILL ve SIGSTOP) dışında, "daha güçlü" olan bir sinyal kavramı yoktur.

Bir sinyal, bir alma işleminin sinyali nasıl işlediği (ve bu sinyal için varsayılan eylemin ne olduğu) ile ilgili olarak yalnızca başka bir sinyalden "daha güçlü" olabilir. Örneğin, varsayılan olarak hem SIGTERM hem de SIGINT sonlandırmaya yol açar. Ancak SIGTERM'i görmezden gelirseniz, SIGINT hala devam ederken, işleminizi sonlandırmaz.


0

Birkaç sinyal haricinde, sinyal işleyicileri çeşitli sinyalleri yakalayabilir veya bir sinyal alındığında varsayılan davranış değiştirilebilir. Ayrıntılar için signal(7)man sayfasına bakın.


Evet, ancak bir tek kelimenin "anlamını" bilmiyorsam, sinyali yakalamak anlamsızdır çünkü başvurumda ne yapacağımı bilemeyeceğim. GNU C, örneğin SIGQUIT ve SIGTERM arasındaki farkı açıklar. Ancak SIGINT hakkında çok az bilgi veriyor: gnu.org/s/libc/manual/html_node/Termination-Signals.html
Mecki

" SIGINT(" Program kesme ") sinyali, kullanıcı INTR karakterini (normalde C-c) yazdığında gönderilir ." "SIGINT 2 Term Interrupt klavyeden" Ctrl-C tuşlarına bastığınızda SIGINTgönderilir. Süreç normalde ölür. Daha ne verecek?
Ignacio Vazquez-Abrams

Potansiyel olarak, programcının kullanıcının ctrl-c'ye bastığında sahip olacağını varsayması gereken niyetin bir açıklaması olabilir, yani mesajın anlam bilgisi. Örnek olarak, HTTP spesifikasyonu, bir kullanıcı bir GET isteği gönderdiğinde, sunucunun bir yanıt geri göndermek dışında herhangi bir şey yapmasını istediğini varsaymaması gerektiğini açıkça belirtir.
bdsl
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.