/* Prosessien välistä kommunikointia yksinkertaisimmillaan: Signaalit. * * Testattu GNU/Linux x86_64 -ympäristössä. Muualla ei ole mitään * takuita. Pitäisi kyllä olla ihan standardia Unix -kamaa. * * Näin voidaan C-kielen avulla määritellä käsittelijäaliohjelmia * käyttöjärjestelmän välittämille signaaleille, jotka voivat tulla * muilta prosesseilta tai päätettä näppäilemällä. Tämä ohjelma * käsittelee päätenäppäilyt Ctrl-C, Ctrl-Z ja Ctrl-\ itse * määrämällään tavalla. Samat signaalit voidaan lähettää unixissa * apuohjelmalla kill ("man kill" kertoo tietenkin enemmän.). * * Suomalaisesta näppäimistöstä on pirun vaikea loitsia "Ctrl-\" * -painallusta, jonka SIGABRT -käsittelijä poimisi. Mutta saman asian * voit tosiaan tehdä, kun toisessa pääteikkunassa samaan koneeseen * komennat:: * * kill -6 PID * * missä PID on käynnissä olevan sigesim-ohjelman prosessitunnus. Sen * löydät vaikkapa katsomalla omien prosessiesi listaa:: * * ps -u `whoami` * * Ohjelman lopetusta kannattaa pyytää signaaleilla SIGTERM tai SIGINT * eli "kill -15 PID" tai "kill -2 PID". Jos ei MIKÄÄN MUU AUTA, niin * "kill -9 PID" yleensä lopettaa ohjelman eikä sitä voi estää edes * ohjelman määrittelemällä signaalikäsittelijällä. Lopetussignaalit * kannattaa käsitellä sovelluksissa, ja tehdä tarvittavat * automaattiset tallennukset, resurssien vapauttamiset, ynnä muut * elintärkeät operaatiot, ja sitten lopettaa ohjelma * tyylikkäästi. Tuo signaali KILL eli "kill -9" on armoton, koska * sitä ei voi napata lopputoimien suorittamiseksi! * Esim. tietokantaserverin tappaminen kill -9:llä voi korruptoida * kannan! Varo. Käytä ensisijaisesti INT ja TERM -signaaleja. * */ #include #include #include /* C:ssä pitää esitellä nimet ennen niiden käyttöä. Aliohjelmien * toiminnallisuuden määrittely kuitenkin vasta koodin lopussa. */ void handle_sigint(int); void handle_sigtstp(int); void handle_sigabrt(int); int main(int argc, char **args) { /* Seuraavilla kutsuilla määritellään omat signaalikäsittelijät * (annetaan signal.h:ssa määritellyt kokonaislukutunnukset ja * muistiosoitteet itse kirjoitettuihin aliohjelmiin. C-kielessä * aliohjelman nimi ilman aktivointia eli sulkumerkkisyntaksia * "aliohj()" tarkoittaa aliohjelman alun muistiosoitetta.): */ signal(SIGINT, handle_sigint); signal(SIGTSTP, handle_sigtstp); signal(SIGABRT, handle_sigabrt); for(;;){ printf("Tämä ohjelma menee nyt unille...\n"); pause(); printf("Heräsi unilta! Ilmeisesti tuli signaali!\n"); } return 1; } void handle_sigint(int a) { /* Viritetään käsittelijä varmuuden vuoksi uudelleen, koska joissain * toteutuksissa kuulemma signaalikäsittelijä tulkitaan * kertakäyttöiseksi ja se on tässä vaiheessa palannut * oletuskäsittelijäksi. */ signal(SIGINT, handle_sigint); printf("\"Ctrl-C\" signaali poimittu. Mutta ei tehdä mitään\n"); } void handle_sigtstp(int a) { signal(SIGTSTP, handle_sigtstp); printf("\"Ctrl-Z\" signaali poimittu. Mutta ei tehdä mitään\n"); } void handle_sigabrt(int a) { printf("\"Ctrl-\\\" signaali poimittu. Lopetetaan.\n"); exit(0); }