Kromě problému „příliš mnoho signálů“ lze signály explicitně ignorovat. Od man 2 signal
:
If the signal signum is delivered to the process, then one of the
following happens:
* If the disposition is set to SIG_IGN, then the signal is ignored.
Signály lze také blokovat. Od man 7 signal
;
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
Blokované i ignorované sady signálů jsou zděděny podřízenými procesy, takže se může stát, že nadřazený proces vaší aplikace jeden z těchto signálů ignoroval nebo zablokoval.
Co se stane, když je doručeno více signálů předtím, než proces dokončí zpracování předchozích? To záleží na OS. signal(2)
výše uvedená manuálová stránka o tom pojednává:
- Systém V resetuje rozložení signálu na výchozí. Horší je, že rychlé doručení více signálů by mělo za následek rekurzivní (?) volání.
- BSD automaticky zablokuje signál, dokud nebude obsluha hotová.
- V Linuxu to závisí na příznacích kompilace nastavených pro GNU
libc
, ale očekával bych chování BSD.
Nemůžete věřit, že každý vyslaný signál bude doručen. Například linuxové jádro "spojí" SIGCHLD, pokud proces trvá dlouho, než zpracovává SIGCHLD z ukončeného podřízeného procesu.
Abychom odpověděli na další část vaší otázky, signály se „zařadí do fronty“ uvnitř jádra, pokud v příliš krátkém intervalu dorazí několik různých signálů.
Měli byste použít sigaction()
pro nastavení obsluhy signálu pomocí sa_sigaction
člen siginfo_t
, nastavením sa_mask
člen siginfo_t
argumentujte opatrně. Myslím, že to znamená alespoň maskování všech „asynchronních“ signálů. Podle manuálové stránky pro Linux sigaction()
, budete také maskovat signál, který je zpracováván. Myslím, že byste měli nastavit sa_flags
členem SA_SIGINFO, ale nemohu si vzpomenout, proč mám tuto pověru. Věřím, že díky tomu bude váš proces obsluhován signálem, který zůstane nastavený bez podmínek závodu a který nebude přerušován většinou ostatních signálů.
Napište svou funkci zpracování signálu velmi, velmi pečlivě. V zásadě stačí nastavit globální proměnnou, která bude indikovat, že byl zachycen signál, a nechat zbytek procesu řešit požadovanou akci pro tento signál. Signály budou tímto způsobem maskovány na co nejkratší dobu.
Také budete chtít velmi důkladně otestovat svůj kód zpracování signálu. Dejte to do malého testovacího procesu a odešlete co nejvíce signálů SIGUSR1 a SIGUSR2, možná ze 2 nebo 3 speciálních programů pro odesílání signálů. Zamíchejte také některé další signály, až budete mít jistotu, že váš kód zvládne SIGUSR1 a SIGUSR2 rychle a správně. Připravte se na obtížné ladění.
Pokud používáte linux a pouze linux, můžete přemýšlet o použití signalfd()
vytvořit deskriptor souboru, který můžete select()
nebo dotazujte, abyste tyto signály přijali. Pomocí signalfd()
může usnadnit ladění.
Je zaručeno doručení signálu v tom smyslu, že pokud proces úspěšně zavolá kill
, pak cíl přijme signál. To je asynchronní:odesílatel nemá žádný způsob, jak zjistit, kdy je signál přijat nebo zpracován. To však nezaručuje, že signál bude doručen. Cíl může zemřít dříve, než stihne zpracovat signál. Pokud cíl ignoruje signál v době, kdy je vydán, signál nebude mít žádný účinek. Pokud cíl přijme více instancí stejného čísla signálu, než je může zpracovat, signály se mohou (a obvykle jsou) sloučit:pokud pošlete stejný signál dvakrát do procesu, nemůžete vědět, zda proces signál přijme. jednou nebo dvakrát. Signály jsou většinou navrženy tak, aby zabily proces nebo jako způsob, jak přimět proces, aby věnoval pozornost, nejsou určeny pro komunikaci jako takovou.
Pokud potřebujete spolehlivé doručení, potřebujete jiný komunikační mechanismus. Mezi procesy existují dva hlavní komunikační mechanismy:roura umožňuje jednosměrnou komunikaci; soket umožňuje obousměrnou komunikaci a více připojení ke stejnému serveru. Pokud potřebujete, aby cíl zpracoval tolik oznámení, kolik jej odešlete, odešlete bajty přes kanál.