Linux proqram skeletində siqnallar. Niyə bir çox Unix proqramları USR1 kimi siqnallardan istifadə edir? Reentrant funksiyalarının siyahısı

Bu bölmədə, gələn siqnalların (məsələn, kəsilmələr) işlənməsi prosesini addım-addım nəzərdən keçirəcəyik xarici dünya, həmçinin proqram səhvləri. Proqram səhvləri əsasən yanlışlıq səbəbindən yaranır

xüsusi təlimatları yerinə yetirərkən və ya üzən nöqtə əməliyyatları səbəbindən yaddaşa uyğun olmayan girişlər. Xarici dünyadan gələn ən ümumi siqnallar: kəsmək(kəsmək) – bu siqnal siz düyməni basdığınız zaman göndərilir DEL; çıxış(çıxmaq) – FS simvolu ilə yaradılmışdır ( ctl-\); bağlanma(asmaq) – telefonun asılması nəticəsində yaranan və tamamlama(dayandırmaq) – kill əmri ilə yaradılır. Yuxarıdakı hadisələrdən biri baş verdikdə, həmin terminaldan işləyən bütün proseslərə siqnal göndərilir və əksini ifadə edən konvensiyalar olmadıqda, siqnal prosesi dayandırır. Əksər siqnallar yaddaş zibilini yaradır ki, bu da sazlama üçün lazım ola bilər. (Bax: adb(1) və sdb(l).)

Siqnal sisteminin çağırışı standart hərəkəti dəyişir. Onun iki arqumenti var: birincisi siqnalı təyin edən nömrə, ikincisi ya funksiyanın ünvanı, ya da siqnala məhəl qoymamağı və ya standart hərəkətləri bərpa etməyi əmr edən koddur. Fayl müxtəlif arqumentlərin təsvirlərini ehtiva edir. Belə ki,

#daxildir

siqnal(SIGINT, SIG_IGN);

zamanı kəsilmənin nəzərə alınmamasına səbəb olur

siqnal(SIGINT, SIG_DFL);

standart hərəkəti bərpa edir - prosesi bitirir. Bütün hallarda siqnal siqnalın əvvəlki dəyərini qaytarır. İkinci arqument funksiyanın adıdırsa (eyni şəkildə elan edilməlidir mənbə faylı), siqnal baş verdikdə çağırılacaq. Bu funksiyadan ən çox istifadə edilən proqram müvəqqəti faylı silmək kimi çıxışa hazırlaşmağa imkan verməkdir:

#daxildir

char *tempfile = "temp.XXXXXX";

extern onintr();

mktemp (tempfile);

/* Emal olunur... */ exit(0);

onintr() /* kəsildikdə sil */

əlaqəni kəsmək (şabbə faylı); çıxış(1);

Niyə əsas siqnalı yoxlayıb yenidən çağırmalıyıq? Siqnalların göndərildiyini unutmayın Hamısı bu terminalda işləyən proseslər. Müvafiq olaraq, proqram interaktiv şəkildə icra edilmədikdə (lakin & ilə) əmr prosessoru ona kəsilmələrə məhəl qoymamağa imkan verir, beləliklə, proqram qeyri-interaktiv məqsədlər üçün nəzərdə tutulmuş fasilələrlə dayandırılmayacaq. fon prosesləri. Əgər proqram nə olursa olsun bütün fasilələrin onintr-ə göndərilməli olduğu elanı ilə başlayırsa, bu cəhdi rədd edir. komanda prosessoru Arxa fonda işləyən proqramı qoruyun.

Yuxarıda təqdim olunan həll, kəsilmənin idarə edilməsinin vəziyyətini yoxlamağa və əvvəllər onlara məhəl qoyulmadıqda, kəsilmələrə məhəl qoymamağa davam etməyə imkan verir. Kod siqnalın geri qayıtmasını nəzərə alır əvvəlki vəziyyət xüsusi siqnal. Əgər əvvəllər siqnallara məhəl qoyulmayıbsa, proses onlara məhəl qoymağa davam edəcək; əks halda onların qarşısını almaq lazımdır.

Daha mürəkkəb proqram kəsilməni kəsmək və onu davam edən əməliyyatı ləğv etmək və öz əmr dövrəsinə qayıtmaq tələbi kimi şərh etmək istəyə bilər. Məsələn, mətn prosessorunu götürək: yazmağa çox uzun müddət ara vermək proqramdan çıxmağınızla və bütün işinizi itirməyinizə səbəb olmamalıdır. Bu vəziyyətdə aşağıdakı kodu yaza bilərsiniz:

#daxildir

#daxildir jmp_buf sjbuf;

əgər (siqnal(SIGINT, SIG_IGN) != SIG_IGN) siqnal(SIGINT, onintr);

setjmp(sjbuf); /* cari vəziyyəti yığında saxlamaq */ (;;) (

/* əsas emal dövrü */

onintr() /* kəsildikdə sıfırlayın */

siqnal(SIGINT, onintr); /* növbəti fasilə üçün sıfırlama */ printf("\nKəsilmə\n");

longjmp(sjbuf, 0); /* saxlanmış vəziyyətə qayıt */ )

setjmp.h faylı jmp_buf tipini yığın mövqeyinin saxlanıla biləcəyi obyekt kimi elan edir; sjbuf bu tip obyekt kimi elan edilir. setjmp(3) funksiyası proqramın icra olunduğu yeri qeyd edir. Dəyişən dəyərlər yadda saxlanmır. Kesinti baş verdikdə, mesajı çap edə, bayraqlar təyin edə və ya başqa bir şey edə bilən onintr proqramına zəng başlayır. Longjmp funksiyası setjmp-də saxlanan obyekti qəbul edir və setjmp çağırışından sonra proqramda idarəetmə nöqtəsinə qaytarır. Beləliklə, idarəetmə (və stek mövqeyi) əsas proqramda əsas dövrənin daxil olduğu nöqtəyə qaytarılır.

Qeyd edək ki, fasilə baş verdikdən sonra siqnal yenidən onintr-ə təyin edilir. Bu zəruridir, çünki siqnallar qəbul edildikdə avtomatik olaraq standart hərəkəti bərpa edir.

Bəzi proqramlar sadəcə olaraq heç bir anda dayandırıla bilməz, məsələn, emal zamanı mürəkkəb quruluş data, ona görə də siqnalları aşkar edə bilmək lazımdır. Bəlkə növbəti həll– biz kəsilmə idarəçisinin bayraq təyin etməli və exit və ya longjmp çağırmaq əvəzinə qayıtmalıyıq. İcra dayandırıldığı yerdən davam edəcək və kəsilmə bayrağı daha sonra yoxlanıla bilər.

Bu yanaşmanın bir çətinliyi var. Fərz edək ki, fasilə göndərilərkən proqram terminaldan oxuyur. Göstərilən rutin düzgün çağırılır, bayraqları təyin edir və qaytarır. Əgər bu, həqiqətən də, yuxarıda qeyd edildiyi kimi olsaydı, yəni proqramın icrası “dayandığı yerdən” davam edərdi, o zaman proqram istifadəçi yeni sətir yazana qədər terminaldan oxumağa davam etməli olardı. Bu davranış çaşqınlıq yarada bilər, çünki istifadəçi proqramın nə oxuduğunu bilmir və yəqin ki, siqnalın dərhal qüvvəyə minməsinə üstünlük verəcəkdir. Bu problemi həll etmək üçün sistem oxumağı tamamlayır, lakin nə baş verdiyini göstərən bir səhv statusu ilə; errno ləğv edilmiş sistem çağırışını göstərmək üçün errno.h-də müəyyən edilmiş EINTR olaraq təyin edilib.

Buna görə də, siqnalları kəsən və onlardan sonra davam edən proqramlar sistem çağırışlarının kəsilməsi nəticəsində yaranan "səhvlərə" hazırlanmalıdır. (Ehtiyatlı olmaq üçün sistem zəngləri terminalı oxumaq, gözləmək və dayandırmaqdır.) Belə bir proqram standart girişi oxumaq üçün aşağıdakı koddan istifadə edə bilər:

#daxildir extern int errno;

əgər (oxumaq(0, &c, 1)<= 0) /* EOF или прерывание */

if (errno == EINTR) ( /* EOF kəsilmə nəticəsində yaranıb */ errno = 0; /* növbəti dəfə sıfırlayın */

) else ( /* faylın həqiqi sonu */

Siqnalın tutulması digər proqramların icrası ilə birləşdirilərsə, diqqət yetirməli olduğunuz son bir incəlik. Fərz edək ki, proqram fasilələri idarə edir və əlavə olaraq digər proqramların icra oluna biləcəyi metodu (red-də olduğu kimi) ehtiva edir. Sonra kod bu kimi görünəcək:

if (fork() == 0) exclp(...);

siqnal(SIGINT, SIG_IGN); /* əcdad müdaxilələrə məhəl qoymur */

gözləyin(&status); /* uşaq işləyərkən */ siqnal(SIGINT, onintr); /* fasilələri bərpa edin */

Bu niyə belədir? Bütün proseslərinizə siqnallar göndərilir. Tutaq ki, çağırdığınız proqram redaktorun etdiyi kimi öz fasilələrini idarə edir. Uşaq proqramını dayandırsanız, o, siqnalı qəbul edəcək və əsas dövrəyə qayıdacaq və yəqin ki, terminalınızı oxuyacaq. Ancaq zəng edən proqram da uşaq proqramını gözləməkdən oyanacaq və terminalınızı oxuyacaq. İki terminal oxu prosesinə sahib olmaq hər şeyi çaşdırır, çünki sistem əslində hansı proqramın hər giriş sətirini alacağına qərar vermək üçün sikkə vurur. Bunun qarşısını almaq üçün ana proqram uşaq icra edənə qədər fasilələrə məhəl qoymamalıdır. Bu nəticə sistemdə siqnal emalında əks olunur:

#daxildir

sistem(lər) /* əmr satırını yerinə yetirmək s */ char *s;

int statusu, pid, w, tty;

int (*istat)(), (*qstat)();

əgər ((pid = çəngəl()) == 0) (

exclp("sh", "sh", "–c", s, (char *) 0); çıxış(127);

isstat = siqnal (SIGINT, SIG_IGN); qstat = siqnal(SIGQUIT, SIG_IGN);

isə ((w = gözləyin(&status)) != pid && w != –1)

əgər (w == –1) statusu = –1;

siqnal (SIGINT, istat); siqnal (SIGQUIT, qstat); qayıtmaq vəziyyəti;

Bir kənara, siqnal funksiyasının bir qədər qəribə ikinci arqumenti var. Bu, əslində tam ədədi qaytaran funksiyanın göstəricisidir və o, həm də siqnal funksiyasının özünün növüdür. İki dəyər, SIG_IGN və SIG_DFL, düzgün tipdədir, lakin onlar heç bir mümkün real funksiyaya uyğun gəlməyəcək şəkildə seçilir. Xüsusilə maraqlananlar üçün onların PDP-11 və VAX üçün necə təsvir olunduğuna dair bir nümunə; təsvirlər siqnaldan istifadəni təşviq etmək üçün kifayət qədər iyrənc olmalıdır.h.

#SIG_DFL (int (*)())0 təyin edin

#SIG_IGN təyin edin (int (*)())1

həyəcan siqnalları

Sistem zəng siqnalı( n) vasitəsilə prosesinizə SIGALRM siqnalının göndərilməsinə səbəb olur n saniyə Müvafiq vaxt ərzində bir şeyin baş verdiyini təmin etmək üçün həyəcan siqnalı istifadə edilə bilər, əgər bir şey baş verərsə, SIGALRM söndürülə bilər, proses həyəcan siqnalı alaraq nəzarəti qaytara bilər.

Vəziyyəti izah etmək üçün, time-out adlı proqramı nəzərdən keçirək, o, başqa bir əmr işlədir; bu əmr müəyyən vaxta qədər tamamlanmayıbsa, həyəcan sönəndə dayandırılacaq. Məsələn, 5-ci Fəsildən watchfor əmrini xatırlayın. Onu qeyri-müəyyən müddətə işlətmək əvəzinə, siz saatlıq limit təyin edə bilərsiniz:

$ fasilə - 3600 dmg & üçün watch

Taymoutdakı kod əvvəlki iki bölmədə müzakirə olunan demək olar ki, hər şeyi təsvir edir. Uşaq yaradılır; əcdad həyəcan təbili çalır və uşağın işini bitirməsini gözləyir. Siqnal daha tez gəlsə, uşaq məhv olur. Uşağın çıxış statusunu qaytarmağa cəhd edilir.

/* fasilə: proses üçün vaxt məhdudiyyəti təyin edir */

#daxildir

#daxildir

int pid; /* uşaq proses identifikatoru */

char *proqram adı; əsas(argc, argv)

int sec = 10, status, onalarm();

proqram adı = argv;

if (argc > 1 && argv == ‘–’) ( san = atoi(&argv);

argc––; argv++;

əgər (argc< 2)

error("İstifadə: %s [–10] əmri", proqram adı); əgər ((pid=fork()) == 0) (

execvp(argv, &argv); xəta("%s başlana bilmədi", argv);

siqnal(SIGALRM, onalarm); həyəcan siqnalı (san);

əgər (gözləyin(&status) == –1 || (status & 0177) != 0) xəta("%s öldürüldü", argv);

exit((status >> 8) & 0377);

onalarm() /* həyəcan siqnalı alınarsa uşaq prosesini dayandırın */

öldür (pid, SIGKILL);

Məşq 7.18. Yuxunun necə həyata keçirildiyini təxmin edə bilərsinizmi? İpucu: fasilə (2). Hansı şəraitdə (əgər varsa) yuxu və həyəcan bir-birinə müdaxilə edə bilər? ~

Tarix və biblioqrafiya

Kitabda təqdim olunmayıb ətraflı təsviri UNIX sisteminin tətbiqi, xüsusən də koda mülkiyyət hüquqlarının olması səbəbindən. Ken Thompsonun 1978-ci ilin iyulunda BSTJ-də nəşr olunan "UNIX tətbiqi" məqaləsi əsas ideyaları təsvir edir. Həmin nömrədəki “UNIX sistemi – retrospektiv” məqalələrində də eyni mövzu qaldırılır

"BSTJ" və "UNIX vaxt mübadiləsi sisteminin təkamülü" ( UNIX-in təkamülü– vaxt mübadiləsi sistemləri), Springer-Verlag jurnalında “Kompüter Elmində Mühazirə Qeydləri”ndə Dil Dizaynı və Proqramlaşdırma Metodologiyası üzrə Simpoziumun materiallarında dərc edilmişdir.

1979-cu il № 79. Hər iki əsər Dennis Ritchie tərəfindən yazılmışdır.

Readslow proqramı Peter Weinberger tərəfindən icad edilmişdir sadə çarə tamaşaçılara şahmat oyunu nümayiş etdirmək Belle proqramları Ken Tomson və Joe Condon şahmat turniri zamanı. Belle oyun vəziyyətini fayla yazdı; Müşahidəçilər çox qiymətli dövrlər almamaq üçün oxunuş sürətindən istifadə edərək faylı sorğuladılar. ( Yeni versiya Belle aparatı öz ana maşınında kiçik hesablamalar aparır, ona görə də bu problem artıq mövcud deyil.)

Tom Daff bizi spname yazmağa ilhamlandırdı. Ivor Durham, David Lamb və James Saxe tərəfindən "İstifadəçi interfeyslərində orfoqrafiya korreksiyası" məqaləsi istifadəçi interfeysləri), CACM tərəfindən 1983-cü ilin oktyabrında nəşr edilmiş, e-poçt proqramı kontekstində orfoqrafik korreksiyanın həyata keçirilməsi üçün bir qədər fərqli layihədir.

Siqnallar proqram təminatının kəsilməsidir. Onlar UNIX-də proseslər və Linux, Mac OS kimi UNIX-ə bənzər əməliyyat sistemləri arasında əlaqə yaratmaq üçün istifadə olunur.

Siqnallar 1970-ci ildə Bell Labs UNIX-dən bəri istifadə olunur və indi rəsmi olaraq POSIX standartı ilə müəyyən edilir. Prosesə bir siqnal gəldikdə, əməliyyat sistemi prosesin icrasının normal gedişatını kəsir və bildiriş verir.

Hansı əməliyyat sistemindən istifadə etməyinizdən asılı olmayaraq, şübhəsiz ki, tətbiqlərinizin bloklandığını və düzgün işləməkdən imtina etdiyini yaşayacaqsınız. Unix, Linux-da prosesi dərhal öldürmək üçün istifadə edə biləcəyiniz "kill" əmri var, ancaq bu deyil, bir az sonra bu barədə danışacağam. Bu məqalədə “Unix/Linux-da Kill Command” sizə necə edəcəyinizi izah edəcəyəm və göstərəcəyəm hazır nümunələr kill yardım proqramının müxtəlif əmrləri.

Əmrləri və Siqnalları öldürün

Öldürmə əmrini verdiyiniz zaman siz əslində sistemə siqnal göndərirsiniz və ona pozulmuş tətbiqi dayandırmağı tapşırırsınız. İstifadə edilə bilən cəmi 60 siqnal var, lakin həqiqətən bilmək lazımdır ki, SIGTERM (15) və SIGKILL (9).

Komandadan istifadə edərək bütün siqnallara baxa bilərsiniz:

# öldür -l

MacOS-da:

Bütün siqnallar haqqında danışmağa çalışacağam, amma əvvəlcə yalnız ən vacib və tez-tez istifadə olunanlar haqqında danışacağıq.

Əsas siqnallar

Aşağıdakı siqnallar POSIX standartının bir hissəsidir. Hər bir siqnal müəyyən edilmiş makrodur Sistem başlıq faylı. Onlar adətən SIG prefiksi olmadan qısaldılır; məsələn SIGHUP tez-tez sadəcə HUP kimi istinad edilir.

SIGTERM– Bu siqnal işləyən prosesi dayandırmağı tələb edir. Bu siqnal göz ardı edilə bilər. Proqram yaxşı bağlandıqda, bu o deməkdir ki, ona öz irəliləyişini xilas etmək və resursları boşaltmaq üçün vaxt verilib. Yəni prosesi dayandırmağa “məcbur etmədi”.

SIGKILL– SIGKILL siqnalı prosesin dərhal işini dayandırmasına səbəb olur. Proqram bu siqnalı laqeyd edə bilməz. Yadda saxlanmamış irəliləyiş itiriləcək.

"Öldürmək" üçün sintaksis.

Komanda sintaksisi belədir:

# öldürmək PID(lər)

# öldür [-s] [-l] %pid

Standart siqnal (əgər göstərilməyibsə) SIGTERM-dir. Bu siqnal kömək etmədikdə və işləmədikdə, prosesi zorla dayandırmaq üçün "öldürmək" üçün aşağıdakı seçimlərdən istifadə edə bilərsiniz:

# SIGKILL PID-i öldürün

# öldürmək -9 PID

burada “-9” SIGKILL siqnalına istinad edən bayraqdır.

Qurtulmaq istədiyiniz proqram üçün hansı PID-dən istifadə edəcəyinizi bilmirsinizsə, əmri yerinə yetirin:

$ps -aux

Və əgər bilirsənsə xüsusi tətbiq(məsələn, apache), onda siz lazımsızları silə və bu xidmət üçün bütün prosesləri göstərə bilərsiniz:

$ ps -aux | grep apache

Və hər şeyi göstərəcək çalışan proqramlar PID(ləri) ilə birlikdə.

Məsələn, bir proqramı öldürmək üçün aşağıdakı əmri yerinə yetirirəm:

# öldürmək -9 3629

Onu da qeyd etmək lazımdır ki, siz eyni vaxtda birdən çox prosesi işlədə bilərsiniz ki, onlar “öldürülə”:

# öldürmək -9 PID1 PID2 PID 3

Konfiqurasiya fayllarını yenidən yükləyin və ya yardım proqramlarını yenidən başladın:

# öldürmək -1 PID_sayı

Xüsusilə faydalı siqnallar HUP, INT, kill, STOP, CONT və 0 daxildir.

Seçimlər bunlardır:

-s siqnal_adı
Qeyri-standart siqnal göndərmək üçün siqnalı təyin edən simvolik siqnal adı.

-l
Operand göstərilməyibsə, siqnal adlarını göstərin; Əks halda, çıxış_statusuna uyğun gələn siqnalın adını yazın.

-siqnal_adı
Defolt olaraq TERM-ə göndəriləcək siqnalı təyin edən simvolik siqnal adı.

-siqnal_nömrəsi
TERM-ə göndəriləcək defolt siqnalı təyin edən qeyri-mənfi onluq tam ədəd.

Aşağıdakı PID-lərin xüsusi mənası var:
-1 Əgər super istifadəçi, o zaman siqnalı bütün proseslərə yayır; əks halda bütün proseslərə yayımlanır-
istifadəçi üçün.

Ən çox istifadə edilən siqnallardan bəziləri bunlardır:

  • 1 HUP (qapaq) - telefonu bağla.
  • 2 INT (interrupt) - kəsilmə.
  • 3 QUIT (çıxmaq) - çıxmaq.
  • 6 ABRT (abort) - fasilələr.
  • 9 ÖLDÜR (tutula bilməyən, laqeyd olmayan öldürmə)
  • 14 ALRM ( zəngli saat) - həyəcan siqnalı.
  • 15 TERM (proqramın dayandırılması siqnalı) - Siqnalın dayandırılması üçün proqram.

PKill

"pkill" əmri müntəzəm ifadələrin inkişaf etmiş nümunələrindən və digər uyğun meyarlardan istifadə etməyə imkan verir. PID-dən istifadə etmək əvəzinə, indi proses adını daxil etməklə proqramı öldürə bilərsiniz. Məsələn, Firefox brauzerini öldürmək üçün sadəcə əmri yerinə yetirin:

#pkill Firefox

Çünki nümunəyə uyğundur müntəzəm ifadə, siz həmçinin proses adının bir hissəsini belə daxil edə bilərsiniz:

#pkillfire

Yanlış prosesləri "öldürməmək" üçün, uyğun prosesləri siyahıya almaq üçün "pgrep -l [proses_adı]" edə bilərsiniz.

pkill əmrinin daha çox variantları var, məsələn, "-u" seçimini göstərsəniz, istifadəçi adı və ya ID-ni təyin etməyə imkan verəcəkdir. Bu misalda biz “heç kim” istifadəçisinə məxsus bütün proseslərə TERM siqnalını göndəririk:

# pkill - heç kim

Öldür

Killall PID əvəzinə proses adından istifadə edir və o, eyni adla prosesin bütün nümunələrini "öldürür". Məsələn, bir neçə nümunədən istifadə edirsinizsə Firefox brauzeri, hamısını əmrlə öldürə bilərsiniz:

#Filfoxu öldür

Gnome-da Nautilus-u əmrlə yenidən başlada bilərsiniz:

#killallnautilus

xkill

Xkill edir qrafik olaraq tətbiqi "öldürün". Terminalda "XKill" daxil etdiyiniz zaman siçan kursoru dərhal "xaç" halına gələcək. Sizə lazım olan tək şey xəta törədən proqramda "çarpaz" düyməsini sıxmaqdır və o, proqramı dərhal öldürəcək. Əgər maraqlanırsınızsa, XKill funksiyasını aktivləşdirmək üçün klaviatura qısayolu əlavə edə bilərsiniz.

İstifadə olunan digər siqnallar

SIGABRT

Bu siqnal əməliyyatı dayandırmaq üçün prosesə siqnal göndərir. ABRT anormal sonlanma siqnalı vermək üçün C proqramlaşdırma dilinin abort() funksiyasını çağırdıqda adətən prosesin özünə yönəldilir, lakin hər hansı digər siqnal kimi istənilən prosesdən istiqamətləndirilə bilər.

SIGALRM, SIGVTALRM və SIGPROF

ALRM, VTALRM və/və ya PROF siqnalı həyəcan funksiyasına (məsələn, təyinedici kimi) çağırışla müəyyən edilmiş vaxt limiti bitdikdə prosesə göndərilir.

ALRM

İndiki vaxt və ya saat keçəndə göndərilir.

VTALRM

Proses tərəfindən istifadə edilən CPU vaxtı bitdikdə göndərilir.

PROF

Bir proses tərəfindən istifadə edilən CPU vaxtı və proses adından sistem bitdikdə göndərilir.

SIGBUS

Avtobus siqnalı avtobus xətası ilə nəticələndikdə prosesə göndərilir. Yaddaş girişinin səhv hizalanması və ya çatışmayan fiziki ünvan kimi bu siqnalla nəticələnən şərtlər.

SIGCHLD

CHLD siqnalı uşaq prosesi dayandırıldıqda, kəsildikdə və ya kəsildikdən sonra davam etdikdə prosesə göndərilir. Siqnalın ümumi istifadələrindən biri, açıq bir sistem çağırışı olmadan, dayandırıldıqdan sonra uşaq prosesi tərəfindən istifadə olunan resursları təmizləmək üçün OS-yə siqnal verməkdir.

SIGCONT

CONT siqnalı əməliyyat sisteminə əvvəllər STOP və ya TSTP siqnalı ilə dayandırılmış prosesi yenidən başlatmağı əmr edir. biri mühüm xüsusiyyətlər Bu siqnal Unix qabığında işin idarə edilməsidir.

SIGFPE

FPE siqnalı, sıfıra bölmə kimi səhv hesab əməliyyatları yerinə yetirdikdə prosesə göndərilir.

SIGHUP

HUP siqnalı idarəetmə terminalı bağlandıqda prosesə göndərilir. O, əvvəlcə ardıcıl xətlərin düşməsindən sonra bir prosesi xəbərdar etmək üçün nəzərdə tutulmuşdu (asılmalardan məsul olan HUP). IN müasir sistemlər, bu siqnal adətən psevdo və ya virtual terminal nəzarətinin bağlandığını bildirir.

SIGILL

Zərərli, naməlum və ya imtiyazlı əmrləri (təlimatları) yerinə yetirməyə cəhd edərkən prosesə göndərilən ILL siqnalı.

SIGINT

INT siqnalı istifadəçi prosesi dayandırmaq istədikdə idarəetmə terminalından prosesə göndərilir. Bu adətən Control-C düyməsinə basmaqla başlanır, lakin bəzi sistemlərdə "sil" və ya "sındır".

SIGKILL

KILL siqnalı dərhal işləməyi dayandırmaq üçün bir prosesə göndərilir. SIGTERM və SIGINT-dən fərqli olaraq, bu siqnal tutula və ya nəzərə alına bilməz və qəbuledici proses bu siqnalı aldıqdan sonra heç bir təmizləmə apara bilməz.

SIGPIPE

PIPE siqnalı, digər ucuna qoşulmuş bir proses olmadan boruya yazmağa cəhd edərkən prosesə göndərilir.

SIGQUIT

QUIT siqnalı, istifadəçi prosesdən tullantı yerinə yetirməyi tələb etdikdə onun idarəetmə terminalından prosesə göndərilir.

SIGSEGV

SEGV siqnalı etibarsız virtual yaddaş arayışı və ya seqmentasiya xətası etdikdə, yəni seqmentasiya pozuntusunu həyata keçirdikdə prosesə göndərilir.

SIGSTOP

STOP siqnalı OS-yə prosesi dayandırmağı bildirir ki, daha sonra davam edə bilsin.

SIGTERM

TERM siqnalı onun dayandırılmasını tələb etmək üçün prosesə göndərilir. “Öldür” siqnalından fərqli olaraq, proses zamanı onu şərh etmək və ya nəzərə almamaq olar. Bu, resursların buraxılmasını dayandırmaq və zəruri hallarda vəziyyəti saxlamaq üçün prosesə "gözəl" icra etməyə imkan verir. Qeyd etmək lazımdır ki, SIGINT SIGTERM ilə demək olar ki, eynidir.

SIGTSTP

TSTP siqnalı onun idarəetmə terminalı prosesinə göndərilir və müvəqqəti olaraq dayandırılmasını bildirir. Bu, adətən istifadəçi Control-Z düyməsini basması ilə başlayır. SIGSTOP-dan fərqli olaraq, bu proses siqnal idarəedicisini qeyd edə və ya siqnalı görməməzliyə vura bilər.

SIGTTIN və SIGTTOU

TTIN və TTOU siqnalları müvafiq olaraq arxa fonda (tty) terminaldan oxumağa və ya yazmağa cəhd etdikdə prosesə göndərilir. Bir qayda olaraq, bu siqnal yalnız nəzarət altında olan proseslərdən istifadə etməklə əldə edilə bilər işçi paneli; demonların idarəetmə terminalları yoxdur və heç vaxt bu siqnalı qəbul etməməlidir.

SIGUSR1 və SIGUSR2

USR1 və USR2 siqnalları prosesə göndərilir və göstərir istifadəçi müəyyən edilmişdirşərtlər.

SIGPOLL

POLL siqnalı asinxron I/O hadisəsi baş verdikdə prosesə göndərilir.

SIGSYS

SYS siqnalı sistem çağırışına pis arqument ötürdükdə prosesə göndərilir.

SIGTRAP

TRAP siqnalı, sazlayıcının xəbərdar edilməsini xahiş etdiyi bir vəziyyət yarandıqda, məsələn, müəyyən bir funksiya yerinə yetirildikdə və ya dəyişənin xüsusi dəyəri dəyişdikdə prosesə göndərilir.

SIGURG

URG siqnalı, rozetkada oxumaq üçün təcili və ya diapazondan kənar məlumatlar olduqda prosesə göndərilir.

SIGXCPU

XCPU siqnalı CPU-dan müəyyən müddətdən artıq istifadə etdikdə prosesə göndərilir dəyəri təyin edin, istifadəçi tərəfindən quraşdırılmışdır. XCPU siqnalının gəlməsi prosesə hər şeyi tez saxlamağa imkan verir aralıq nəticələr və SIGKILL siqnalından istifadə edərək əməliyyat sistemi tərəfindən öldürülməzdən çox əvvəl çıxır.

SIGXFSZ

XFSZ siqnalı fayl maksimum icazə verilən dəyərdən böyüdükdə (müəyyən edilmiş dəyəri aşdıqda) prosesdə göndərilir.

SIGRTMIN SIGRTMAX-a

RTMIN - RTMAX siqnalları xüsusi məqsədlər üçün istifadə üçün nəzərdə tutulub. Onlar real vaxt siqnallarıdır.

Fərqli siqnallar

Aşağıdakı siqnallar POSIX tərəfindən standartlaşdırılmır, lakin bəzən bəzi sistemlərdə istifadə olunur.

SIGEMT

EMT siqnalı emulyatorun kəsilməsi baş verdikdə proses zamanı göndərilir.

SİGİNFO

Nəzarət terminalından status sorğusu alındıqda INFO siqnalı davam edir.

SIGPWR

PWR siqnalı sistem elektrik kəsilməsi ilə qarşılaşdıqda prosesdə göndərilir.

SIGLOST

LOST siqnalı "fayl kilidi" itirildikdə prosesə göndərilir.

SIGVİNÇ

VİNÇ siqnalı idarəetmə terminalı ölçüsünü dəyişdikdə prosesə göndərilir.

Klaviaturadan siqnalların göndərilməsi

Siqnallar klaviaturadan göndərilə bilər. Bir neçə standart standart dəyər aşağıda verilmişdir. Varsayılan olaraq, kəsmə siqnallarının göndərilməsi üçün klaviatura qısa yolları stty əmrindən istifadə etməklə müəyyən edilə bilər.

CTRL-C

SIGINT göndərin (kesinti). Varsayılan olaraq bu, prosesin dayandırılmasına səbəb olur.

CTRL-Z

SIGTSTP göndərin (Dayandırın). Varsayılan olaraq, bu, prosesin bütün əməliyyatları dayandırmasına səbəb olur.

CTRL-\

SIGQUIT göndərin (Çıxın). Varsayılan olaraq, bu, prosesin dərhal dayandırılmasına və nüvənin yenidən qurulmasına səbəb olur.

CTRL-T

SIGINFO (INFO) göndərin. Varsayılan olaraq, bu, əməliyyat sisteminin əmr haqqında məlumatı göstərməsinə səbəb olur. Bütün sistemlərdə dəstəklənmir.

nəticə

Tətbiqlər səhv davrandıqda və sistemin donmasına səbəb olduqda, kompüterinizi yenidən başlatmaq və sessiyanı yenidən başlamaq çox cəlbedicidir. Bu "öldür" əmrləri ilə siz sistem qəzasına səbəb olan və ya səbəb ola biləcək tətbiqlərin pis davranışını daha yaxşı idarə edə bilərsiniz. Bununla da yekunlaşıram bu mövzu"Unix/Linux-da öldürmə əmri."

İndi başqa bir proqramı nəzərdən keçirək - 13–14-3.c:

/* Xüsusi SIGINT siqnal emalı ilə proqram */ #include #daxildir /* my_handler funksiyası – xüsusi siqnal idarəedicisi */ void my_handler(int nsig)( printf("%d siqnalı alın, CTRL-C sıxıldı\n", nsig); ) int main(void)( /* Proses cavabını təyin edin siqnal SIGINT */ (void)signal(SIGINT, my_handler /*Bu nöqtədən başlayaraq proses SIGINT */ while(1); Siyahı 13-14.3.

SIGINT siqnalının xüsusi işlənməsi ilə proqram (13-14-3.c). Bu proqram "Siqala məhəl qoymayan proqramın icrası" bölməsindəki proqramdan fərqlidir. SIGINT Bu proqram "Siqala məhəl qoymayan proqramın icrası" bölməsindəki proqramdan fərqlidir."Çünki o, siqnal emalını təqdim edir< CTRL >xüsusi funksiya. Bu proqramı yazın, tərtib edin və işə salın, düymələrin basılmasına cavabını yoxlayın Və< CTRL >xüsusi funksiya. Bu proqramı yazın, tərtib edin və işə salın, düymələrin basılmasına cavabını yoxlayın<4>.

və düymələrin vuruşlarında

SIGINT və SIGQUIT siqnallarının xüsusi emalı üçün əvvəlki proqramın modifikasiyası< CTRL >xüsusi funksiya. Bu proqramı yazın, tərtib edin və işə salın, düymələrin basılmasına cavabını yoxlayın<4>Proqramı əvvəlki bölmədən elə dəyişdirin ki, o, həm də düymələrin basılması haqqında mesaj çap etsin. Bu proqram "Siqala məhəl qoymayan proqramın icrası" bölməsindəki proqramdan fərqlidir.. Siqnal emalı üçün eyni funksiyadan istifadə edin SIGQUIT . Kompilyasiya edin və işə salın, düzgün işlədiyini yoxlayın. Siz həmçinin əmri ilə proqramı başqa terminaldan silməli olacaqsınız.

öldürmək

Bir siqnala əvvəlki cavabın bərpası İndiyə qədər nümunələrdə sistem çağırışının qaytardığı dəyəri nəzərə almamışıq siqnal() Bu proqram "Siqala məhəl qoymayan proqramın icrası" bölməsindəki proqramdan fərqlidir.. Bu sistem çağırışı faktiki olaraq əvvəlki siqnal idarəçisinə göstərici qaytarır və siqnala ləğv edilmiş cavabı bərpa etməyə imkan verir. Siqnalın ilkin cavabını qaytaran 13-14-4.c proqramının nümunəsini nəzərdən keçirək

5 xüsusi siqnal emalından sonra. #daxildir int i=0; /* Siqnalın emal sayının sayğacı */ void (*p)(int); /* Əvvəlki siqnal idarəedicisinin ünvanının daxil ediləcəyi göstərici */ /* my_handler funksiyası – xüsusi siqnal idarəedicisi */ void my_handler(int nsig)( printf("Siqnal qəbulu %d, CTRL-C sıxıldı\n", nsig); i = i+1; /* 5-ci emaldan sonra ilkin reaksiyanı siqnala qaytarırıq */ if(i == 5) (void)signal(SIGINT, p) int main(void)( /* Əvvəlki işləyicinin ünvanını xatırlayaraq, proses reaksiyamızı SIGINT siqnalına təyin edin */ p = siqnal (SIGINT, my_handler); / while(1); Siyahı 13-14.4.

SIGINT siqnalının xüsusi işlənməsi ilə proqram (13-14-4.c).

Proqramı yazın, tərtib edin və işə salın.

SIGUSR1 və SIGUSR2 siqnalları. Prosesləri sinxronlaşdırmaq üçün siqnallardan istifadə UNIX əməliyyat sistemində iki siqnal mövcuddur ki, onların mənbələri yalnız sistem çağırışı ola biləröldür() . Kompilyasiya edin və işə salın, düzgün işlədiyini yoxlayın. Siz həmçinin əmri ilə proqramı başqa terminaldan silməli olacaqsınız və ya əmr , siqnallardır. Siqnal emalı üçün eyni funksiyadan istifadə edin SIGUSR1 SIGUSR2 . Onlar adətən baş vermiş hadisə haqqında məlumatı bir istifadəçi prosesindən digərinə ötürmək üçün istifadə olunur.

siqnal rabitə vasitələri , siqnallardır. Siqnal emalı üçün eyni funksiyadan istifadə edin SIGUSR1 5-ci seminarın materiallarında (“Boru vasitəsilə əlaqəli proseslər arasında ikiistiqamətli rabitənin təşkili üçün proqramın yazılması, tərtibi və icrası” bölməsi) boru vasitəsilə əlaqəli proseslərin kommunikasiyası nəzərdən keçirilərkən borunun bir istiqamətli rabitə kanalı olduğu, və bir boru ilə iki istiqamətdə rabitənin təşkili üçün proseslərin qarşılıqlı sinxronlaşdırılması mexanizmlərindən istifadə etmək lazımdır. Sinxronizasiya üçün siqnallardan istifadə edərək bir boru vasitəsilə ana proses və uşaq proses arasında ikitərəfli alternativ əlaqəni təşkil edin

bölmədən proqramı dəyişdirərək. "Boru vasitəsilə əlaqəli proseslər arasında bir istiqamətli əlaqəni təşkil etmək üçün proqramın icrası" Seminar 5. Qabaqcıl tapşırıq , siqnallardır. Siqnal emalı üçün eyni funksiyadan istifadə edin SIGUSR1.

: yalnız siqnallardan istifadə edərək iki proses arasında tam ədədi bit istiqamətində köçürün Əməliyyat otağında icra iplərini həyata keçirərkən Linux sistemi (“UNIX-də mövzunun başa düşülməsi” bölməsindən başlayaraq 6-7-ci seminarlara baxın.İcra başlığının ID-si , siqnallardır. Siqnal emalı üçün eyni funksiyadan istifadə edin SIGUSR1. Funksiya pthread_self() ") siqnalları istifadə edə bilməz siqnallar , siqnallardır. Siqnal emalı üçün eyni funksiyadan istifadə edin SIGUSR1.

Yumurtlama prosesinin dayandırılması. Waitpid() sistem çağırışı. Siqnal SIGCHLD

3-4 seminarların materiallarında (bölmə " Prosesi bitirmək. exit() funksiyası ") prosesin dayandırılmasını öyrənərkən deyilirdi ki, əgər uşaq proses öz ana prosesindən əvvəl çıxırsa və ana proses onun haqqında məlumat almaqda maraqlı olmadığını açıq şəkildə göstərmirsə. tamamlama statusu uşaq prosesi, sonra tamamlanan proses sistemdən tamamilə yox deyil, vəziyyətdə qalır bitmiş performans(zombi prosesi) ya ana proses başa çatana qədər, ya da valideyn bu məlumatı almağa qərar verənə qədər.

Belə məlumatları əldə etmək üçün ana proses sistem çağırışından istifadə edə bilər waitpid() və ya onun sadələşdirilmiş forması gözləyin(). Sistem zəngi waitpid() ana prosesə ya uşaq prosesi başa çatana qədər ana prosesi bloklamaqla, ya da vaxtaşırı WNOHANG seçimi ilə çağırılanda bloklamadan dayandırılmış uşaq prosesinin statusu haqqında məlumatı sinxron şəkildə əldə etməyə imkan verir. Bu məlumat 16 bit tutur və kursumuzda aşağıdakı kimi deşifrə edilə bilər:

Hər bir uşaq proses çıxdıqda ana prosesinə xüsusi siqnal göndərir. SIGCHLD, bütün proseslərin defolt reaksiyası "siqnala məhəl qoymur". Sistem çağırışı ilə birlikdə belə bir siqnalın olması waitpid() ana proses tərəfindən başa çatdırılmış proseslərin vəziyyəti haqqında məlumatın asinxron toplanması təşkil etməyə imkan verir.

wait() və waitpid() sistem zəngləri

Prototiplər sistem zəngləri

#daxildir #daxildir pid_t waitpid(pid_t pid, int *status, int variantları); pid_t wait(int *status);

Sistem zənglərinin təsviri

Bu təsvir sistem zənglərinin tam təsviri deyil, kursumuza uyğunlaşdırılıb. Qəbul etmək tam təsviri UNIX Təlimatına baxın.

Sistem zəngi waitpid() cari prosesin icrasını bloklayır, ya pid parametrinin dəyəri ilə müəyyən edilmiş onun yaranmış prosesi başa çatana qədər və ya cari proses defolt "prosesi bitir" cavabı və ya xüsusi funksiyanın idarə edilməsi cavabı olan bir siqnal alana qədər. Əgər yumurtlama prosesi parametrlə müəyyən edilir sistem çağırışı yerinə yetirildikdə pid bitmiş vəziyyətdədir, sistem çağırışı cari prosesi bloklamadan dərhal geri qayıdır.

pid parametri ana prosesin dayandırılmasını gözlədiyi uşaq prosesi aşağıdakı kimi müəyyən edir:

  • Əgər pid > 0 olarsa, pid identifikatoru ilə prosesin başa çatmasını gözləyin.
  • Əgər pid = 0 olarsa, onda biz ana prosesin aid olduğu qrupda hər hansı uşaq prosesinin dayandırılmasını gözləyirik.
  • Əgər pid = -1 olarsa, o zaman hər hansı bir yaranan prosesin dayandırılmasını gözləyirik.
  • Əgər pid< 0 , но не –1 , то ожидаем завершения любого порожденного процесса из группы , идентификатор которой равен mütləq dəyər pid parametri.

Kursumuzdakı variantlar parametri iki qiymət ala bilər: 0 və WNOHANG . WNOHANG dəyəri istənilən halda cari prosesi bloklamadan zəngin dərhal qayıtmasını tələb edir.

Sistem çağırışı pid parametri ilə göstərilənlər arasından tamamlanmış uşaq prosesi aşkar edərsə, bu proses kompüter sistemindən çıxarılır və onun dayandırılması statusu haqqında məlumat status parametrində göstərilən ünvanda saxlanılır. Bu məlumat bizim üçün əhəmiyyət kəsb etmirsə, status parametri NULL olaraq təyin edilə bilər.

Xitamlanmış proses aşkar edildikdə, sistem çağırışı onun ID-sini qaytarır. Zəng ilə edilibsə quraşdırılmış seçim WNOHANG və pid tərəfindən müəyyən edilmiş yaranmış proses mövcuddur, lakin hələ çıxmayıb, sistem çağırışı 0 qaytaracaq. Bütün digər hallarda mənfi dəyər qaytarır. İstifadəçi tərəfindən işlənmiş siqnalın baş verməsi ilə əlaqəli zəngdən qayıdış daha sonra sistem dəyişəninin dəyəri ilə müəyyən edilə bilər errno == EINTR və zəng yenidən edilə bilər.

Gözləmə sistemi çağırışı, pid = -1, variantları = 0 parametr dəyərləri ilə waitpid sistem zəngi üçün sinonimdir. yaradılan prosesdir.

/* Tamamlanmış iki uşaq prosesinin vəziyyəti haqqında məlumatın asinxron qəbulu ilə proqram */ #include #daxildir #daxildir #daxildir #daxildir /* my_handler funksiyası SIGCHLD siqnalının işləyicisidir */ void my_handler(int nsig)( int status; pid_t pid; /* Biz tamamlanmış prosesin statusunu sorğulayırıq və eyni zamanda onun identifikatorunu tapırıq */ if(( pid = waitpid(-1, &status, 0) )< 0){ /* Если возникла ошибка – сообщаем о ней и продолжаем работу */ printf("Some error on waitpid errno = %d\n", errno); } else { /* Иначе анализируем статус завершившегося процесса */ if ((status & 0xff) == 0) { /* Процесс завершился с явным или неявным вызовом функции exit() */ printf("Process %d was exited with status %d\n", pid, status >> 8);< 0){ printf("Can\"t fork child 1\n"); exit(1); } else if (pid == 0){ /* Child 1 – завершается с кодом 200 */ exit(200); } /* Продолжение процесса-родителя – порождаем Сhild 2 */ if((pid = fork()) < 0){ printf("Can\"t fork child 2\n"); exit(1); } else if (pid == 0){ /* Child 2 – циклится, необходимо удалять с помощью сигнала! */ while(1); } /* Продолжение процесса-родителя – уходим в цикл */ while(1); return 0; } ) else if ((status & 0xff00) == 0)( /* Proses siqnalla öldürüldü */ printf("Proses %d %s siqnalla öldürüldü\n", pid, status &0x7f,(status & 0x80 ) ? "əsas faylı ilə" : "əsas faylsız"); * Uşaq 1 yaradın */ if((pid = fork()) Siyahı 13-14.5. Tamamlanmış iki uşaq prosesinin vəziyyəti haqqında məlumatın asinxron qəbulu ilə proqram (13-14-5.c). öldürmək istənilən siqnal nömrəsi ilə. . Kompilyasiya edin və işə salın, düzgün işlədiyini yoxlayın. Siz həmçinin əmri ilə proqramı başqa terminaldan silməli olacaqsınız.

Siqnal və ya virtual kəsmə sistemin bir prosesə göndərdiyi və ya bir prosesin digərinə göndərdiyi mesajdır. Proses siqnal qəbul etdikdə, proses proqramının icrası dayandırılır və idarəetmə siqnal işləyicisinin alt proqramına (funksiyasına) ötürülür. Siqnal idarəedicisi yerinə yetirildikdən sonra kəsilmiş proqramın icrası kəsildiyi yerdən davam etdirilir.

Əməliyyat sistemi təmin edir çox sayda siqnal növləri, lakin bu növlərin əksəriyyəti sistem məqsədləri üçün qorunur - bunlar əməliyyat sisteminin prosesə göndərdiyi siqnallardır. Bununla belə, proseslərin öz aralarında mübadilə edə biləcəyinə dair siqnallar da var.

Əksər siqnallara standart cavab siqnalı qəbul edən prosesi dayandırmaqdır, yəni proses idarə etmək üçün nəzərdə tutulmadığı bir siqnal alırsa, qəbuletmə prosesi dayandırılır. Bununla belə, əksər siqnal növləri üçün proses idarəedici quraşdıra bilər siqnal verilir və ya bu siqnalı iqnor etmək üçün təyin edin.

Əgər proses “könüllü” dayandırma vəziyyətindədirsə (məsələn, yuxu sistemi çağırışının yerinə yetirilməsi nəticəsində yaranırsa), o zaman siqnalın işlənməsinin nə olmasından asılı olmayaraq, “prosesi yuxudan oyatmaq” siqnalını aldıqda, yuxu sistemi çağırışı başa çatır. dərhal.

Prosesdəki siqnal idarəedicisi prototipli funksiyaya bənzəyir:

Boş funksiya_adı(int nişan növü);

Bu funksiyanın parametri siqnal növüdür (eyni işləyici müxtəlif növ siqnalları emal etmək üçün quraşdırıla bilər).

Öz siqnal idarəçinizi təyin etmək, onu ləğv etmək və ya siqnala məhəl qoymamaq üçün siqnal sistemi çağırışından istifadə edin.

Siqnal idarəedici funksiyaları bunlardır normal funksiyalar C, onlar bütün qlobal görünən dəyişənlərə və funksiyalara çıxış əldə edirlər. Bununla belə, proqramın icrasının hansı nöqtəsində işləyici funksiyasının çağırılacağını bilmədiyimiz üçün daxil olarkən xüsusi diqqət yetirməliyik. qlobal strukturlar bu funksiyadan alınan məlumatlar. Axınları emal edən funksiyalar üçün başqa bir vacib tələb var - yenidən giriş. Siqnal işləyicisi proqramın icrasının istənilən nöqtəsində çağırıla biləcəyi üçün (və bəzi şərtlərdə bir siqnalın işlənməsi zamanı başqa bir siqnal idarəedicisi çağırıla bilər), işləyicilər reentrant tələbini ödəyən funksiyalardan istifadə etməlidirlər, yəni. eyni vaxtda onlar proqramda başqa yerdə çağırılırlar. Əslində, reentrant tələbi funksiyanın bu resurslara girişi sinxronlaşdırmağa diqqət etmədən heç bir qlobal resurslardan istifadə etməməsini təmin etməkdən irəli gəlir. Bəzi I/O funksiyaları, o cümlədən printf() funksiyası reentrant deyil. Bu bir nəticə deməkdir printf funksiyaları

() başqa funksiyanın çıxışına mane ola bilər. Aşağıda siqnal işləyicilərindən zəng etmək təhlükəsiz olan reentrant funksiyalarının siyahısı verilmişdir.

Reentrant funksiyalarının siyahısı

posix_trace_event()

timer_getoverrun()

Proses öldürmə sistemi çağırışından istifadə edərək PID-ini bildiyi hər hansı digər prosesə siqnal göndərə bilər (məşum adına baxmayaraq, bu sistem çağırışı mütləq ünvanlandığı prosesi öldürmür). Bəzi hallarda prosesin özünə bir siqnal göndərməsi lazım ola bilər ki, bu, yüksəltmə sistemi çağırışı ilə edilə bilər;

Bəzi siqnal növləri

Siqnal növləri rəqəmli nömrələrlə müəyyən edilir, lakin proqramlaşdırma tez-tez sistem daxil fayllarında müəyyən edilmiş simvolik siqnal adlarından istifadə edir. Aşağıda ən çox istifadə edilən siqnal adlarından bəziləri verilmişdir:

Bu siqnal onu qəbul edən prosesin dayandırılmasına səbəb olur. Bu, göz ardı edilə bilməyən və öz işləyicinizi təyin edə bilməyən yeganə siqnaldır

Bu siqnal prosesi dayandırmaq tələbidir. Bu siqnalın verilməsi, məsələn, əmr daxildir (sistem çağırışı deyil!) kill .

Bu siqnal vaxt intervallarını saymaq üçün istifadə olunur. Proses həyəcan siqnalı və ya ayarlayıcı sistem zənglərindən istifadə edərək və müddəti bitdikdən sonra vaxt intervalı təyin edə bilər müəyyən edilmiş interval sistem ona SIGALRM siqnalı göndərəcək.

SIGUSR1 və SIGUSR2

Bu siqnalların arxasında heç bir qorunmuş siqnal yoxdur. sistem tapşırıqları. Proseslər bu siqnalları bir-birinə göndərə və uyğun gördükləri kimi şərh edə bilər.

Siqnal növləri haqqında ətraflı məlumat üçün funksiya təsvirinə baxın

Bir çox Unix proqramı USR1 və USR2 kimi siqnalları qəbul edir. Məsələn, yeniləmək üçün icra edilə bilən fayl Tez Nginx üçün kill -USR2 göndərirsiniz.

Mənim başa düşdüyüm budur ki, USR1 "istifadəçi tərəfindən müəyyən edilmiş" siqnaldır, yəni proqramı yaradan şəxs ondan "bağlamaq" və ya "loglarınızı boşaltmaq" və ya "foo-nu min dəfə çap etmək" və ya hər hansı bir mənada istifadə edə bilər. Amma başa düşə bilmirəm ki, niyə bu özbaşına addan istifadə etmək məcburiyyətindədirlər. Niyə -YÜKSƏLƏNMƏYİ öldürməyəsiniz və ya -GRACEFUL_SHUTDOWN-u öldürməyəsiniz? Unix yalnız müəyyən siqnallara malikdirmi?

Biz bununla məşğul olduğumuz müddətdə Nginx aşağıdakı siqnallardan da istifadə edir (sənədlərə baxın):

  • TERM, INT: sürətli bağlanma
  • ÇIXIN: zərif tamamlama
  • HUP:
    • Konfiqurasiyanı yenidən başladın
    • Yeni konfiqurasiya ilə yeni iş axınlarına başlayın
    • Köhnə iş axınlarının zərif şəkildə bağlanması
  • USR1: jurnal fayllarını açın
  • USR2: icra sənədlərini tez yeniləyin
  • VİNÇ: Nəzakətlə iş axınlarını dayandırın

HUP? Vinç? Bu adların səbəbi nədir? Bu haqda daha ətraflı haradan öyrənə bilərəm?

6 cavab

ƏS-də mövcud olan siqnallar ƏS tərəfindən müəyyən edilir (adətən POSIX-dən sonra) - onlar "sətirlər" deyil, standart adları olan tam sabitlərdir. USR1 və USR2, tərtibatçının istədiyi hər hansı ixtiyari istifadə üçün nəzərdə tutulmuş xüsusi mənası olmayan iki siqnaldır.

Sizin üzərində Linux maşını siqnal və siqnalın işlənməsi haqqında ümumi məlumat üçün man 7 siqnalını oxuyun.

Hadisələrə cavab olaraq həmin siqnalları vermək üçün ƏS ilə işləməyə hazırsınızsa, digər siqnalların mənasını ləğv edə bilərsiniz. Siz, məsələn, HUP-u "konfiqurasiyanı yenidən yükləmək" mənasını verə bilərsiniz - əgər prosesin heç vaxt dayanmayacağına (terminalın itirilməsi) əminsinizsə və ya istifadəçinin deyil, OS-nin göndərdiyi hallarla məşğul olmağa hazırsınızsa. HUP siqnalı.

HUP sürüşmək üçün uyğun deyil. Bu siqnal, idarəetmə terminalı faylın sonuna çatdıqda prosesə göndərilir. Əvvəlki dövrlərdə idarəetmə terminalları adətən serial portlara, ola bilsin ki, modem xətti vasitəsilə birləşdirilirdi telefon xətti. Əgər telefon əlaqəsi işə salındıqda, yerli modem Carrier Detect xəttini aşağı salaraq, nüvə faylının tamamlanması hesabatının göndərilməsinə səbəb olacaq və ötürülən siqnal SIGHUP.

VINCH "pəncərə dəyişdirmək" üçün uyğun deyil. Nəzarət terminalı ölçüsünü dəyişərsə, prosesə göndərilir. Aşkar səbəblərə görə ölçüsünü dəyişə bilən terminallar adətən pseudo-terminallardır və onlar son nəticədə pəncərə mühitində (məsələn, xterm) işləyən terminal emulyatoru ilə təmsil olunurlar.

Çünki siqnal adları standartlaşdırılıb (POSIX). USR1 siqnalını çatdırmaq və çatdırmaq istəsəniz -UPGRADE almaq üçün öz öldürmə faylınızı yaza bilərsiniz, lakin UNIX ilə gələn standart öldürmə onu tanımayacaq.

Alternativ olaraq, tərcüməni sizin üçün etmək üçün ləqəb, funksiya və ya qabıq skripti yarada bilərsiniz, məsələn, bash ləqəbindən istifadə etməklə:

Ləqəb upgrade="kill -USR1"

Signal.h başlıq faylı siqnal adlarını onların real həyata keçirilməsindən asılı dəyərlərinə uyğunlaşdırır.

WINCH baxımından mən bunun bir az iyrənc olduğunu düşünürəm. Bu, pəncərə ölçüsü dəyişdirildikdə (xüsusilə onların idarəetmə terminalı pəncərəsi dəyişdirildikdə) proqramlara çatdırılan siqnaldır.

İşçi tellərini zərif şəkildə bağlamaq üçün bundan istifadə etmək, prosesin heç vaxt terminalda işləməyəcəyinə zəmanət vermədiyiniz halda yaxşı fikir deyil. Bilirəm ki, bir proqram işlətsəm, bu çox mif olardı və o, pəncərəni böyütdüyüm üçün uçuşda bütün işləri ləğv etmək qərarına gəldi :-)

kill -l cəhd edin və cavabı özünüz tapın:

1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGQUIT1) SIGPIAL CHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH13) 2) SIGWINCH13) ) SIGRTMIN 35) SIGRTMIN+ 1 36 ) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN4) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX105) SIGRTMAX5) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX