Lucrul cu semnale de 1 parte în Linux

În sistemele de operare moderne, există conceptul de IPC (Inter-Process Communication - IPC) - un set de metode de schimb de date între procese și / sau fire. Un semnal bidirecțional sunt de schimb. Conceptul de semnale susținute de majoritatea sistemelor de operare, dar, de exemplu, Windows, nu are sprijinul deplin pentru a fi utilizate ca mijloc de IPC - în aceste sisteme de operare, semnalele puse în aplicare numai în biblioteca standard C.







conceptul de semnal

Semnalele pot la un moment aleator (asincronă), pentru a întrerupe procesul să se ocupe de un eveniment. Procesul poate fi întrerupt de un semnal inițiat de un alt proces sau miez. Nucleul utilizează semnale de a notifica procesele de diverse evenimente, cum ar fi finalizarea procesului de copil.

Semnalele au un anumit ciclu de viață. Inițial, este generat un semnal - procesul este trimis sau generate de către nucleu. Semnalul este apoi așteaptă livrarea la procesul de receptor. Se consideră că perioada de așteptare este intervalul de timp dintre crearea semnalului de semnal, și o acțiune care trimite semnalul. La sfârșitul ciclului de viață al unui semnal este sa (recepție) procesul de interceptare și efectuarea de acțiuni asociate cu semnalul.

Semnale simple și fiabile

Există o divizie a semnalului în simplu și de încredere.

Acestea au fost inițial dezvoltate și utilizate semnale simple (fiabile). În conformitate cu principiul său de funcționare sunt similare cu mecanismul canonic pentru manipularea hardware-ul întrerupe la procesor. În cazul în care procesul de dorit un mod special să se ocupe de un semnal, acesta spune kernel-ul cu privire la aceasta, subliniind o funcție specială - de tratare a semnalului. Atunci când livrarea unui proces de semnal al kernel-ului, cât mai curând posibil cauze semnal procesor, întreruperea procesului de lucru. La finalizarea procesului de executare handler continuă până la punctul în care a fost întreruptă.

În loc de a scrie funcția handler, puteți spune pur și simplu nucleul că semnalul cauzează acțiunea, implicit pentru ea, sau că semnalul este ignorat banal.

Acest întreg concept de lucru cu semnale arata destul de bine, până când semnalul vine la proces, la un moment în care el este deja ocupat cu procesarea un alt semnal. Aici și evidente probleme - din nou, cauzate de un handler de semnal poate strica acele resurse partajate (structuri de date partajate și variabile) pe care le utilizează. Mai mult decât atât, în cazul aderării unui număr mare de semnale de proces stivă poate crește fără limită, ceea ce poate cauza funcționarea defectuoasă a programului.

În procesul de rezolvare a problemei au fost dezvoltate semnale de încredere care sunt standardizate în POSIX și încă utilizate în prezent. Mai târziu, în articol, se consideră semnale de încredere.

Semnale și apeluri de sistem

Semnalul poate veni la proces în momentul în care procesul este în interiorul unui apel de sistem, de exemplu, se așteaptă ca introducerea de citire a datelor (). În acest caz, dezvoltarea poate merge la următoarea cale: aplicația nu este încercarea de a intercepta semnalul este întreruptă și miezul (de exemplu, un SIGTERM semnal sosirea) - atunci când terminalul este într-o configurație non-standard, care pot împiedica experiența utilizatorului. Desigur, este posibil de a intercepta semnalul de la terminalul clar în handler de semnal, și apoi du-te afară, dar este destul de dificil de a scrie un handler de semnal, care știa ce face la momentul întreruperii programului pentru a decide dacă să efectueze terminalul curat sau nu.

Până în prezent, există o realizare a semnalelor, care este liber de aceste dezavantaje. Soluția este că, în semnalul de ieșire trebuie să setați doar un steag care indică faptul că semnalul este primit, și apoi trebuie să se asigure revenirea apelului sistem cu un cod de eroare care indică întreruperea semnalului de apel. În continuare, programul trebuie să verifice set de pavilion de tratare a semnalului, și să ia măsuri corespunzătoare, de exemplu, pentru a șterge terminalul și ieșire.

semnal modern determină punerea în aplicare lentă a sistemului de apeluri pentru a returna un EINTR cod de eroare, atunci când acestea sunt întrerupte de semnalul de intrare. apeluri de sistem rapidă trebuie să fie încheiată înainte ca semnalul va fi livrat. Sistem lent apel - apel de sistem, care necesită o perioadă de timp nedeterminată pentru finalizarea acestuia, cum ar fi citit (), așteptați (), scrie (). Toate apelurile de sistem sunt dependente de resurse imprevizibile, cum ar fi acțiunile unei persoane, date de rețea, etc. Ele sunt lente. Bineînțeles, toate celelalte apeluri de sistem - rapid.

De obicei, programul procesează codul de eroare EINTR și în cazul în care nu există nimic fatal, reporneste apelul de sistem. Cele mai multe sisteme de operare de tip Unix sunt în prezent fac acest lucru în mod implicit - trebuie doar pentru a procesa handler de semnal, iar apelul sistem va fi repornit automat. Linux implicit de apel de sistem nu este repornit, dar pentru fiecare proces de semnal poate seta un steag care indică dacă pentru a reporni sistemul de apeluri de sistem lent întrerupt de acest semnal.







Se trimit semnale

Trimiterea semnalelor de la un proces la altul se realizează de obicei folosind apelul sistem kill (). Primul său parametru - proces PID la care este trimis un semnal; al doilea parametru - numărul de semnal. Dacă vrem să trimită un semnal SIGTERM la procesul cu PID 6666, atunci vom folosi ucide apel sistem (), după cum urmează:

apel în loc de valorile PID pozitive pot fi transferate este egală în mărime, dar negativ. Apoi, semnalul va fi trimis la toate procesele grupului cu număr egal cu modulul transmite pid. Dacă PID-ul este 0, semnalul este trimis la toate procesele grupului la care se aplică procesul actual. Aceste oportunități sunt cochilii în principal utilizate pentru controlul de locuri de muncă.

Dacă PID transferă ucide apel sistem () -1, semnalul va fi trimis la toate procesele cu excepția init. Această posibilitate este utilizată pentru oprirea sistemului.

Mai multe informații detaliate cu privire la sistemul de apel ucide (), se referă la două om ucide.

Trimite un proces de semnal se poate folosi creșterea apelului de sistem (), care acceptă un parametru - numărul de semnal. exemplu:

Desigur, fiecare dintre considerate întoarce apel sistem de zero succes și nenul dacă a existat o greșeală.

semnale de interceptare

Toate programele standard POSIX subordonate înregistra semnalele lor de stivuitoare folosind sigaction de apel de sistem (). Acest apel sistem are trei parametri: prima - int Signum - numărul de semnal interceptat. În al doilea rând - struct sigaction * Act - un pointer la o structură care descrie regulile de configurare handler. A treia opțiune - struct sigaction * oact - acceptă deja regulile de tratare a semnalului. Sau a doua sau a treia (dar nu ambele!), Parametrul poate fi setat la NULL, dacă este necesar.

Structura struct sigaction are următoarea descriere:

sa_handler - indicatorul pentru a semnala manipulant, conductorul trebuie declarat după cum urmează:

în cazul în care un singur parametru - numărul de semnal, care a fost în handler. sa_handler poate fi, de asemenea SIG_IGN egal - semnal de proces este ignorat, iar SIG_DFL - semnal determină acțiunea implicită, un astfel de proces de întrerupere.

sa_mask - un set de semnale care ar trebui să fie blocate de un apel dat aceeași structură a procesorului de semnal. Cum de a le instala, este discutat în continuare.

Parametrul sa_flags permite unui proces să modifice comportamentul semnalului. Parametrul poate lua doar patru valori, care, cu toate acestea, pot fi combinate cu ajutorul „OR“ operațiune de biți:

  1. SA_NOCLDSTOP - trimite semnal SIGCHLD numai în cazul întreruperii procesului copil. Dispersarea procesul copil nu trimite un semnal.
  2. SA_NODEFER - emulare simplă (nesigură) de semnalizare.
  3. SA_RESTHAND - după sosirea semnalului de la handler de resetare SIG_DFL.
  4. SA_RESTART - sistem de repornire apel după tratare a semnalului. Dacă indicatorul nu este setat, apelul sistem returnează o EINTR eroare.

Ca de obicei, în cazul în care sigaction de succes () returnează 0, iar în caz de erori - o valoare negativă.

Semnale de proces Mask

Adăugarea semnalelor în sa_mask structura sigset_t, purificarea acestuia etc. implementat folosind sigemptyset () set de funcții, sigfillset (), sigaddset (), sigdelset (). Primele două funcții să ia un parametru - un pointer la o structură sigset_t. Aceste funcții sunt purificate și umple toate semnalele posibile sigset_t structura respectiv.

Ultimele două funcții sunt adăugate, respectiv, și eliminate dintr-o anumită structură de semnal și au doi parametri. Primul lor argument - un pointer la structura sigset_t, iar al doilea - numărul de semnal.

Toate funcțiile de mai sus întoarce 0 în caz de succes și un număr nu este egal cu zero - eroare.

În plus, există o altă caracteristică care verifică dacă semnalul menționat numitul set - sigismember (). Parametrii săi sunt la fel ca sigaddset) parametrii (. Funcția returnează 1 dacă semnalul este în set, 0 - în cazul în care nu este, iar numerele negative - în cazul în care eroarea care a avut loc.

În plus, putem seta lista de alarmă, livrarea care procesul va fi blocat. Acest lucru se face prin funcția sigprocmask (int cum, sigset_t const * set, sigset_t * oldset).

Primul său parametru descrie ce trebuie făcut:

  1. SIG_BLOCK - semnale de la un set de set blocat;
  2. SIG_UNBLOCK - semnale de la un set de set deblocat;
  3. SIG_SETMASK - semnale de la un set de set sunt blocate, celelalte sunt deblocate.

Al doilea parametru este un pointer la același set de semnale care sunt blocate / deblocate. Dacă este NULL, atunci valoarea primului parametru este ignorat de apelul de sistem.

Al treilea parametru - un pointer la o mască de semnal este deja în uz; acesta poate fi pus în NULL, în cazul în care nu sunt necesare aceste date.

sigpending () funcție poate fi utilizată pentru a prelua o listă de semnale în așteptare, care are un singur parametru - un pointer la sigset_t structura, care va fi scris set de semnale de așteptare.

Principii de manipulare semnal de scriere

Una dintre cele mai importante reguli de tratare a semnalului de scriere - handler ar trebui să fie reintrare, și anume aceasta ar trebui să permită o rechemare, atunci când procesul este deja în handler. Ai nevoie să aibă grijă de tratare a semnalului nu utilizează o structură de date globală sau apeluri de sistem lent. Dacă a evita acest lucru, din păcate, este imposibil, este necesar să se aibă grijă de protecția handler de apel invers în timpul structurii de date sau sistem de apel. Acest lucru poate fi realizat prin blocarea în momentul livrării semnalului, care funcționează acum manipulant folosind sigprocmask de apel de sistem (). De exemplu, avem un handler pentru SIGCHLD, să-l bloca, după cum urmează:

Pe lângă toate cele de mai sus, se crede că handler trebuie să fie cât mai simplu posibil - în mod ideal, el ar trebui să pună un steag și la sfârșitul anului, și orice altceva ar trebui să efectueze cea mai mare parte a programului.

concluzie

Cele de mai sus este materialul de bază pentru înțelegerea semnalelor de concept. În principiu, ar trebui să fie suficient că ați început deja să folosească lucrul cu semnale în programele lor.

La sfârșitul ciclului se va spune cum să obțineți (și trimite) datele suplimentare ale formei de undă, dacă îți lipsește informația obișnuită că semnalul venit de undeva în procesul dumneavoastră.