Innholdsserie:
I moderne operativsystemer er det konseptet Inter-Process Communication (IPC) - et sett med metoder for å utveksle data mellom prosesser og/eller tråder. Signaler er en av disse utvekslingsmetodene. Signalkonseptet støttes av de fleste operativsystemer, men det gjør for eksempel ikke Windows. full støtte for bruk som en av IPC-metodene - i slike operativsystemer implementeres signaler kun i standard C-biblioteket.
Signalkonsept
Signaler er i stand til tilfeldig tid(asynkront) avbryte en prosess for å håndtere en hendelse. En prosess kan bli avbrutt av et signal initiert av en annen prosess eller kjerne. Kjernen bruker signaler for å varsle prosesser om ulike hendelser, for eksempel avslutning av en underordnet prosess.
Signaler har en bestemt livssyklus. Først genereres et signal - sendt av en prosess eller generert av kjernen. Signalet venter deretter på levering til destinasjonsprosessen. Det er generelt akseptert at ventetiden for et signal er lik tidsintervallet mellom opprettelsen av et signal og handlingen som dette signalet sender. På slutten Livssyklus signalet fanges opp (mottas) av prosessen og handlingene knyttet til signalet utføres.
Enkle signaler og pålitelige signaler
Det er en inndeling av signaler i enkle og pålitelige.
I utgangspunktet ble enkle (upålitelige) signaler utviklet og brukt. I sitt operasjonsprinsipp ligner de på den kanoniske mekanismen for håndtering av maskinvareavbrudd i prosessoren. Hvis en prosess ønsker å behandle et bestemt signal på en spesiell måte, informerer den kjernen om det, noe som indikerer spesiell funksjon- signalbehandler. Når du leverer et signal til en prosess, ringer kjernen signalbehandleren så snart som mulig, og avbryter prosessen. Når behandleren er ferdig, fortsetter prosessen der den slapp.
I stedet for å skrive din egen behandlerfunksjon, kan du ganske enkelt fortelle kjernen at signalet påkaller standardhandlingen for det, eller at signalet rett og slett ignoreres.
Hele dette konseptet med å jobbe med signaler ser bra nok ut til signalet kommer på et tidspunkt da det allerede er opptatt med å behandle et annet signal. Det er her problemet kommer inn - en gjenoppkalt signalbehandler kan ødelegge de delte ressursene ( generelle strukturer data og variabler) som den bruker. I tillegg ved ankomst et stort antall signaler, kan prosessstakken vokse i det uendelige, noe som kan føre til programfeil.
I prosessen med å løse problemet ble det utviklet pålitelige signaler, som er standardisert i POSIX og brukes den dag i dag. Resten av artikkelen fokuserer på pålitelige signaler.
Signaler og systemanrop
Et signal kan komme til en prosess på et tidspunkt når prosessen er inne i et systemanrop, for eksempel venter på at data skal legges inn i read (). I dette tilfellet kan utviklingen av hendelser følge følgende bane: applikasjonen prøver ikke å avskjære signalet og blir avbrutt av kjernen (for eksempel ankomsten av SIGTERM-signalet) - da forblir terminalen i en ikke-standard konfigurasjon, som kan hindre brukerens arbeid. Selvfølgelig kan du avskjære signalet, tømme terminalen i signalbehandleren og deretter avslutte, men det er ganske vanskelig å skrive en signalbehandler som vet hva programmet gjorde på avbruddstidspunktet for å avgjøre om du skal slette terminalen eller ikke.
For øyeblikket er det en signalimplementering som er fri for disse manglene. Løsningen er å sette et flagg i signalbehandleren for å indikere at signalet ble mottatt, og deretter sørge for at systemanropet kommer tilbake med en feilkode som indikerer at anropet ble avbrutt av signalet. Deretter må programmet sjekke flagget satt av signalbehandleren og utføre Passende tiltak for eksempel tømme terminalen og gå ut.
Moderne signalimplementering tvinger sakte systemanrop returnere en EINTR-feilkode når den blir avbrutt av et innkommende signal. Raske systemanrop må fullføres før signalet leveres. Slow system call - Et system call som krever ubestemt beløp tid å fullføre, for eksempel les (), vent (), skriv (). Alle systemanrop som er avhengige av uforutsigbare ressurser som menneskelige handlinger, nettverksdata og lignende er trege. Naturligvis er alle andre systemanrop raske.
Vanligvis vil programmet behandle EINTR-feilkoden, og hvis ingenting fatalt har skjedd, vil det starte systemanropet på nytt. De fleste Unix-lignende operativsystemer gjør for øyeblikket dette som standard - alt du trenger å gjøre er å håndtere signalet i behandleren, og systemanropet vil bli startet på nytt automatisk. I Linux startes ikke systemanrop på nytt som standard, men for hvert signal kan en prosess sette et flagg for å instruere systemet om å starte trege systemanrop på nytt avbrutt av dette signalet.
Sender signaler
Å sende signaler fra en prosess til en annen gjøres vanligvis ved å bruke kill () systemkallet. Dens første parameter er PID for prosessen som signalet sendes til; den andre parameteren er signalnummeret. Hvis vi ønsker å sende et SIGTERM-signal til en prosess med PID 6666, bruker vi systemkallet kill () slik:
drepe (6666, SIGTERM);I stedet for positivt PID-verdier du kan sende samtalen lik modul, men negativ betydning... Deretter vil signalet sendes til alle prosesser fra gruppen med et tall lik modulen til den overførte PID "a. Hvis PID er 0, så sendes signalet til alle prosesser fra gruppen som den aktuelle prosessen tilhører. Disse funksjoner brukes hovedsakelig av skjell for å kontrollere jobber.
Hvis du sender -1 som PID til kill () systemkallet, vil signalet bli sendt til alle prosesser bortsett fra init "a. Denne funksjonen brukes til å slå av systemet.
Mer detaljert informasjon for kill () systemkall, se mann 2 kill.
En prosess kan sende et signal til seg selv ved å bruke heve () systemkallet, som tar én parameter - signalnummeret. Eksempel:
heve (SIGTERM);Naturligvis returnerer hvert av de betraktede systemkallene null hvis vellykket og ikke null hvis det oppstår en feil.
Avlytting av signaler
Alle POSIX-kompatible programmer registrerer sine signalbehandlere med sigaction () systemkallet. Dette systemanropet har tre parametere: den første er int signum, nummeret på det avlyttede signalet. Den andre, struct sigaction * act, er en peker til en struktur som beskriver reglene for å sette handleren. Den tredje parameteren - struct sigaction * oact - tar allerede etablerte regler signalbehandler. Enten den andre eller den tredje (men ikke begge!) parameter kan settes til NULL om nødvendig.
Struktursigaksjonen har følgende beskrivelse:
struct sigaction (__sighandler_t sa_handler; sigset_t sa_mask; int sa_flags;);sa_handler er en peker til en signalbehandler, og behandleren må deklareres som følger:
void signal_handler (int signo);hvor den eneste parameteren er nummeret på signalet som kom inn i handleren. sa_handler kan også være SIG_IGN — signalet ignoreres av prosessen, og SIG_DFL — signalet utløser en standardhandling, for eksempel å avbryte prosessen.
sa_mask - et sett med signaler som må blokkeres når du kaller en signalbehandler spesifisert i samme struktur. Hvordan du installerer dem er diskutert nedenfor.
Sa_flags-parameteren lar en prosess endre oppførselen til signalet. Parameteren kan bare ha fire verdier, som imidlertid kan kombineres med den bitvise ELLER-operasjonen:
- SA_NOCLDSTOP - send SIGCHLD-signal bare hvis underordnet prosessen blir avbrutt. Å stanse en underordnet prosess fører ikke til at et signal sendes.
- SA_NODEFER - emulering av enkle (upålitelige) signaler.
- SA_RESTHAND - etter at et signal ankommer, tilbakestilles dets behandler til SIG_DFL.
- SA_RESTART – Start systemanropet på nytt etter retur fra signalbehandleren. Hvis flagget ikke er satt, returnerer systemkallet feilen EINTR.
Som vanlig returnerer sigaction () 0 ved suksess, og en negativ verdi ved feil.
Prosesssignalmaske
Legge til signaler til sigset_t sa_mask-strukturen, slette den osv. utføres ved hjelp av settet med funksjoner sigemptyset (), sigfillset (), sigaddset (), sigdelset (). De to første funksjonene tar én parameter, en peker til sigset_t-strukturen. Disse funksjonene klare og fylles med alle mulige signaler henholdsvis sigset_t-strukturen.
De to siste funksjonene legger henholdsvis til og fjerner ett spesifikt signal fra strukturen og har to parametere. Deres første parameter er en peker til sigset_t-strukturen, og den andre er signalnummeret.
Alle funksjonene ovenfor returnerer 0 ved suksess og et tall som ikke er null ved feil.
I tillegg er det en annen funksjon som sjekker om det angitte signalet er i det angitte settet - sigismember (). Parametrene er de samme som for sigaddset (). Funksjonen returnerer 1 hvis signalet er i settet, 0 hvis ikke, og et negativt tall- når det oppstår en feil.
Blant annet kan vi spesifisere en liste over signaler, hvis levering til prosessen vil bli blokkert. Dette gjøres ved å bruke sigprocmask (int how, const sigset_t * set, sigset_t * oldset) funksjonen.
Den første parameteren beskriver hva som bør gjøres:
- SIG_BLOCK - signaler fra settet er blokkert;
- SIG_UNBLOCK - signaler fra settet er blokkert;
- SIG_SETMASK - signaler fra settet blokkeres, resten oppheves.
Den andre parameteren er en peker til det samme settet som signaler blokkeres/oppheves fra. Hvis den er NULL, ignoreres verdien til den første parameteren av systemkallet.
Den tredje parameteren er en peker til en allerede brukt signalmaske; den kan settes til NULL hvis disse dataene ikke er nødvendige.
For å få en liste over ventende signaler, kan du bruke funksjonen sigpending () som tar en enkelt parameter - en peker til sigset_t-strukturen, hvor settet med ventende signaler vil bli skrevet.
Prinsipper for å skrive signalbehandlere
En av de viktigste reglene for skrivesignalbehandlere er at handleren må være reentrant, dvs. den må kunne kalles opp igjen når prosessen allerede er i behandleren. Man bør passe på at signalbehandleren ikke bruker globale datastrukturer eller langsomme systemanrop. Hvis det dessverre er umulig å unngå dette, er det verdt å ta vare på beskyttelsen mot gjentatte anrop fra behandleren mens du arbeider med en datastruktur eller med et systemanrop. Dette kan oppnås ved å midlertidig blokkere leveringen av signalet hvis behandler kjører for øyeblikket ved å bruke sigprocmask () systemkallet. For eksempel har vi en handler SIGCHLD-signal, låser vi den slik:
void chld_handler (int signum) (sigset_t set; if (sigemptyset (& set)) (return;) if (sigaddset (& set, SIGCHLD)) (return;) if (sigprocmask (SIG_BLOCK, & set, NULL)) (return ;) / * gjør noe viktig her * / if (sigprocmask (SIG_UNBLOCK, & set, NULL)) (retur;) return;)I tillegg til alt det ovennevnte, antas det at behandleren skal være så enkel som mulig - ideelt sett bør den sette et visst flagg og avslutte, og resten av programmet skal gjøre resten.
Konklusjon
Materialet ovenfor er grunnleggende for å forstå konseptet med signaler. I utgangspunktet skal det være nok for deg å begynne å bruke arbeid med signaler i programmene dine.
På slutten av syklusen vil du lære hvordan du mottar (og sender) tilleggsdata om et signal hvis du mangler den vanlige informasjonen om at et signal kom fra et sted i prosessen din.
Last ned ressurser
static.content.url = http: //www.site/developerworks/js/artrating/
Artikkel-ID = 495997
ArticleTitle = Arbeide med signaler på Linux, del 1: Grunnleggende om signaler
Signaler er programvareavbrudd. De brukes til kommunikasjon mellom prosesser i UNIX og UNIX-lignende operativsystemer som Linux, Mac OS.
Signaler har eksistert siden Bell Labs UNIX i 1970 og er nå offisielt definert av POSIX-standarden. Når et signal kommer til en prosess, operativsystem avbryter den normale flyten av en prosess og gir varsling.
Det spiller ingen rolle hvilket operativsystem du bruker, du vil garantert støte på at programmene dine blir blokkert og nekter å fungere som de skal. I Unix, Linux er det en "kill"-kommando som du kan bruke til å drepe en prosess umiddelbart, men ikke bare det, men jeg skal snakke om det litt senere. I denne artikkelen "Drap-kommandoen på Unix / Linux" vil jeg forklare og vise videre ferdige eksempler forskjellige kommandoer for kill-verktøy.
Drep kommandoer og signaler
Når du utfører "kill"-kommandoen, sender du det faktisk et signal til systemet og instruerer det om å avslutte den ugyldige robotapplikasjonen. Det er totalt 60 signaler som kan brukes, men alt du egentlig trenger å vite er SIGTERM (15) og SIGKILL (9).
Du kan se alle signaler med kommandoen:
# drepe -l
På min macOS:
Jeg vil prøve å snakke om alle signalene, men til å begynne med, la oss bare snakke om de viktigste og mest brukte.
Grunnleggende signaler
Følgende signaler er en del av POSIX-standarden. Hvert signal er en makro definert i
SIGTERM- Dette signalet ber om å stoppe prosessen som kjører. Dette signalet kan ignoreres. Prosessen får tid til å stenge godt ned. Når et program avsluttes godt, betyr det at det har fått tid til å lagre fremdriften og frigjøre ressurser. Det er med andre ord ikke "tvunget" til å avslutte prosessen.
SIGKILL- SIGKILL-signalet får prosessen til å avslutte arbeidet umiddelbart. Programmet kan ikke ignorere dette signalet. Ulagret fremdrift vil gå tapt.
Syntaks for "drepe".
Kommandosyntaksen er som følger:
# drepe PID(er)
# drepe [-s] [-l]% pid
Standardsignalet (hvis ikke spesifisert) er SIGTERM. Når dette signalet ikke hjelper og ikke fungerer, kan du bruke følgende alternativer for å "drepe" for å avslutte prosessen med makt:
# drep SIGKILL PID
# drep -9 PID
hvor "-9" er flagget refererer til SIGKILL-signalet.
Hvis du ikke vet hvilken PID for applikasjonen du må bruke for å bli kvitt, kjør kommandoen:
$ ps -aux
Og hvis du vet spesifikk applikasjon(for eksempel apache), så kan du luke ut det unødvendige og vise alle prosesser for denne tjenesten:
$ ps -aux | grep apache
Og dette vil vise alt kjører applikasjoner sammen med dens PID(er).
For å drepe applikasjonen kjører jeg for eksempel følgende kommando:
# drep -9 3629
Det er også verdt å merke seg at du kan bruke flere prosesser samtidig slik at de kan "drepes":
# kill -9 PID1 PID2 PID 3
Last inn konfigurasjonsfiler på nytt eller start verktøy på nytt:
# kill -1 number_of_PID
Spesielt nyttige signaler inkluderer HUP, INT, kill, STOP, CONT og 0.
Alternativene er som følger:
-s signalnavn
Et symbolsk signalnavn som spesifiserer et signal for å sende et ikke-standardsignal.
-l
Hvis operanden ikke er spesifisert, vis navnene på signalene; V ellers, skriv navnet på signalet som tilsvarer exit_status.
-signal_navn
Det symbolske navnet på signalet som spesifiserer signalet som skal sendes til TERM som standard.
-signal_nummer
Et ikke-negativt desimaltall som spesifiserer signalet som skal sendes til TERM som standard.
Følgende PID-er er av spesiell betydning:
-1
Hvis superbrukeren, sender et signal til alle prosesser; ellers sendinger til alle prosesser tilhører-
for brukeren.
Noen av de mest brukte signalene:
- 1 HUP (legg på) - legg på.
- 2 INT (avbryte) - avbryte.
- 3 AVSLUTT (avslutt) - avslutt.
- 6 ABRT (avbryt) - avbryter.
- 9 KILL (ikke-fangst, ikke-ignorerbart drap)
- 14 ALRM ( vekkerklokke) - alarm.
- 15 TERM (programvaretermineringssignal) - Programvare for å terminere signalet.
PKill
Pkill-kommandoen lar deg bruke avanserte mønstre av regulære uttrykk og andre samsvarende kriterier. I stedet for å bruke PID, kan du nå drepe applikasjonen ved å skrive inn prosessnavnet. For å drepe Firefox-nettleseren, kjør for eksempel kommandoen:
# pkill Firefox
Siden det stemmer med mønsteret vanlig uttrykk, kan du også skrive inn deler av prosessnavnet, for eksempel:
# pkill brann
For å unngå å drepe feil prosesser, kan du gjøre "pgrep -l [prosessnavn]" i listen over kvalifiserte prosesser.
Pkill-kommandoen har mange flere alternativer, for eksempel hvis du spesifiserer "-u", vil den tillate deg å spesifisere et brukernavn eller ID. I dette eksemplet sender vi TERM-signalet til alle prosesser som eies av brukeren 'ingen':
# pkill -u ingen
Drep alle
Killall bruker prosessnavnet i stedet for PID, og det "dreper" alle forekomster av prosessen med samme navn. For eksempel hvis du bruker flere forekomster Firefox nettleser, kan du drepe dem alle med kommandoen:
# killall firefox
I Gnome kan du starte Nautilus på nytt med kommandoen:
# killall nautilus
xkill
Xkill er grafisk"Drep" applikasjonen. Når du skriver inn "XKill" i terminalen, vil musepekeren umiddelbart bli "kryss". Alt du trenger å gjøre er å trykke på "krysset" på den fornærmende applikasjonen, og den vil drepe applikasjonen umiddelbart. Hvis du er interessert, kan du legge til en hurtigtast for å aktivere XKill-funksjonen.
Flere signaler som brukes
SIGABRT
Dette signalet sender et signal til prosessen om å avbryte operasjonen. ABRT er vanligvis rettet mot selve prosessen når den kaller abort ()-funksjonen til C-programmeringsspråket for å signalisere unormal oppsigelse men det kan sendes fra en hvilken som helst prosess akkurat som alle andre signaler.
SIGALRM, SIGVTALRM og SIGPROF
ALRM, VTALRM og/eller PROF sendes til en prosess når tidsgrensen som er spesifisert for å ringe en alarmfunksjon (som setitimer) utløper.
ALRM
Sendes når den er til stede eller klokken er over tid.
VTALRM
Sendes når prosessortiden som brukes av prosessen er utløpt.
PROF
Sendes når prosessortiden brukt av prosessen og systemet på vegne av prosessen er utløpt.
SIGBUS
Et BUS-signal sendes til en prosess når det resulterer i en bussfeil. Forhold som fører til dette signalet, for eksempel feiljustert minnetilgang eller manglende fysisk adresse.
SIGCHLD
CHLD-signalet sendes til en prosess når en underordnet prosess avsluttes, avbrytes eller gjenopptas etter et avbrudd. En vanlig bruk av signalet er å signalisere operativsystemet til å rydde opp i ressurser som brukes av den underordnede prosessen etter at den avsluttes uten et eksplisitt systemkall.
SIGCONT
CONT-signalet instruerer operativsystemet, og signaliserer om å starte en prosess som tidligere ble suspendert i STOP- eller TSTP-modus. En av viktige funksjoner dette signalet er for å kontrollere arbeidet i Unix-skallet.
SIGFPE
FPE-signalet sendes til en prosess når det utfører feilaktige, aritmetiske operasjoner, for eksempel divisjon med null.
SIGHUP
HUP-signalet sendes til en prosess når kontrollterminalen er lukket. Den ble opprinnelig designet for å varsle en prosess etter et påfølgende linjefall (HUP er ansvarlig for "henger"). I moderne systemer betyr dette signalet vanligvis at kontrollen til den pseudo- eller virtuelle terminalen er lukket.
SIGILL
ILL-signal sendt til en prosess når den prøver å utføre ondsinnede, ukjente eller privilegerte kommandoer (instruksjoner).
SIGINT
Et INT-signal sendes til en prosess fra den kontrollerende terminalen når brukeren ønsker å avbryte prosessen. Dette startes vanligvis ved å trykke på Control-C, men på noen systemer "slett" eller "bryt".
SIGKILL
KILL-signalet sendes til prosessen for å drepe det umiddelbart. I motsetning til SIGTERM og SIGINT, kan ikke dette signalet fanges opp eller ignoreres, og mottaksprosessen kan ikke utføre noen opprydding etter å ha mottatt dette signalet.
SIGPIPE
PIPE-signalet sendes til en prosess når det prøver å skrive til et rør uten noen prosess festet til den andre enden.
SIGQUIT
Et AVSLUTT-signal sendes til en prosess fra dens kontrollerende terminal når brukeren ber om en dumpprosess.
SIGSEGV
Et SEGV-signal sendes til en prosess når den lager en ugyldig kobling virtuell hukommelse eller en segmenteringsfeil, det vil si når den utfører et segmenteringsbrudd.
SIG STOPP
STOPP-signalet forteller operativsystemet å stoppe prosessen for senere gjenopptagelse.
SIGTERM
TERM-signalet sendes til prosessen for å be om oppsigelse. I motsetning til drepesignalet, kan det tolkes eller ignoreres i prosessen. Dette lar prosessen utføre "fin" utførelse for å stoppe ressursfrigjøring og lagre tilstand når det er nødvendig. Det skal bemerkes at SIGINT er nesten identisk med SIGTERM.
SIGTSTP
Et TSTP-signal sendes til den kontrollerende terminalprosessen og ber den om å stoppe midlertidig. Dette initieres vanligvis av brukeren ved å trykke på Control-Z. I motsetning til SIGSTOP, kan denne prosessen registrere en signalbehandler eller ignorere signalet.
SIGTTIN og SIGTTOU
I TTIN og TTOU sendes signaler til en prosess når den prøver å lese eller skrive henholdsvis fra en (tty) terminal i bakgrunnen. Vanligvis kan dette signalet bare mottas av prosesser under kontroll. arbeidspanel; daemoner har ikke kontrollterminaler og bør aldri motta dette signalet.
SIGUSR1 og SIGUSR2
USR1- og USR2-signaler sendes til prosessen og indikerer brukerdefinerte forhold.
SIGPOLL
POLL-signalet sendes i en prosess når en asynkron I/O-hendelse oppstår.
SIGSYS
SYS-signalet sendes i en prosess når det går glipp av et dårlig argument til et systemanrop.
SIGTRAP
Et TRAP-signal sendes til en prosess når en tilstand oppstår som feilsøkeren ba om å bli informert - for eksempel når spesifikk funksjon utføres eller når en spesifikk verdi av en variabel endres.
SIGURG
Et URG-signal sendes til en prosess når stikkontakten har hastedata eller data utenfor rekkevidde tilgjengelig for lesing.
SIGXCPU
XCPU-signalet sendes i prosessen når det brukes prosessor for en tid som overskrider en viss forhåndsinnstilt verdi, satt av brukeren... Ankomsten av XCPU-signalet sikrer at prosessen raskt lagrer alt mellomresultater og den avsluttes i god tid før den går ut av operativsystemet med SIGKILL-signalet.
SIGXFSZ
XFSZ-signalet sendes i prosessen når filen vokser (overskrider den angitte verdien) enn den maksimalt tillatte verdien.
SIGRTMIN til SIGRTMAX
RTMIN - RTMAX-signaler er for tilpasset bruk. De er sanntidssignaler.
Ulike signaler
Følgende signaler er ikke standardisert av POSIX, men brukes noen ganger på enkelte systemer.
SIGEMT
EMT-signalet sendes i prosessen når et emulatoravbrudd oppstår.
SIGINFO
INFO-signalet sendes i prosessen når en statusforespørsel mottas fra den kontrollerende terminalen.
SIGPWR
PWR-signalet sendes i prosess når systemet opplever et strømbrudd.
SIGLOST
Et TAP-signal sendes til en prosess når fillåsen går tapt.
SIGWINCH
WINCH-signalet sendes i en prosess når kontrollterminalen endrer størrelse.
Sender signaler fra tastaturet
Signaler kan sendes fra tastaturet. Flere standardstandarder er oppført nedenfor. Standard snarveistaster for å sende avbruddssignaler kan defineres ved hjelp av stty-kommandoen.
CTRL-C
Send SIGINT (avbryt). Som standard fører dette til at prosessen avsluttes.
CTRL-Z
Send SIGTSTP (suspender). Som standard fører dette til at prosessen stopper alle operasjoner.
CTRL- \
Send SIGQUIT (Avslutt). Som standard fører dette til at prosessen avsluttes umiddelbart og tilbakestille kjernen.
CTRL-T
Send SIGINFO (INFO). Som standard tvinger dette operativsystemet til å vise kommandoinformasjon. Støttes ikke på alle systemer.
produksjon
Når applikasjoner oppfører seg feil og får systemet til å fryse, er det veldig fristende å starte datamaskinen på nytt og starte økten om og om igjen. Med disse "kill"-kommandoene kan du bedre håndtere dårlig oppførsel til programmer som forårsaker eller kan forårsake systemkrasj. Dette konkluderer dette emnet"Drap-kommandoen på Unix / Linux."
Signaler er avbruddsforespørsler som implementeres på prosessnivå. Definert over tretti forskjellige signaler og de finner en lang rekke bruksområder.
- Signaler kan sendes mellom prosesser som et kommunikasjonsmiddel.
- Signaler kan sendes av terminaldriveren for å avbryte eller suspendere prosesser når brukeren trykker spesielle kombinasjoner nøkler som f.eks
eller . - Signaler kan sendes til en rekke formål av en bruker eller en administrator ved å bruke kill-kommandoen.
- Signaler kan sendes av kjernen når en prosess utfører en ulovlig instruksjon som divisjon med null.
- Signaler kan sendes av kjernen for å varsle en prosess om en "interessant" hendelse, for eksempel avslutning av en underordnet prosess eller tilgjengeligheten av data på et I/O-rør.
- En minnedump er en fil som inneholder et minnebilde av en prosess. Den kan brukes til feilsøking.
- KILL-signalet blokkerer ikke og fører til at prosessen avsluttes ubetinget på kjernenivå. Faktisk har prosessen ikke engang tid til å motta dette signalet.
- INT-signal sendes av terminaldriveren når brukeren trykker på en tastekombinasjon
og fungerer som en forespørsel om å fullføre den nåværende operasjonen. Ved å fange dette signalet må enkle programmer avsluttes, eller la standard signalbehandler ødelegge seg selv. Programmer som har en interaktiv kommandolinje bør avbryte den gjeldende operasjonen, rydde opp og gå tilbake til standby. - TERM-signalet er en forespørsel om å avslutte programmet. Prosessen som mottar dette signalet forventes å rydde opp og avsluttes.
- HUP-signalet har to vanlige tolkninger. For det første behandler mange demoner det som en tilbakestillingskommando. Hvis demonen er i stand til å reproklamere sin ære konfigurasjonsfil og tilpasse seg endringer uten å starte på nytt, lar HUP-signalet atferden endre seg.
- For det andre genereres dette signalet noen ganger av terminaldriveren når den prøver å drepe terminalrelaterte prosesser. I utgangspunktet har denne oppførselen blitt bevart fra bruksdagene. kablede tilkoblinger terminaler og modemer. Derav navnet "legg på".
- Det gjør vanligvis csh-familietolkene (tcsh og andre). bakgrunnsprosesser immun mot HUP-signalet slik at de kan fortsette arbeidet selv når brukeren er logget ut. Brukere av sh-familien av tolker (ksh, bash, etc.) kan emulere denne oppførselen med nohup-kommandoen.
- QUIT-signalet ligner på TERM-signalet, bortsett fra at standardbehandleren som standard oppretter en minnedump.
Mange Unix-programmer aksepterer signaler som USR1 og USR2. For eksempel for å oppdatere kjørbar fil for nginx on the fly, sender du kill -USR2.
Jeg forstår at USR1 er et "brukerdefinert" signal, som betyr at den som har laget programmet kan bruke det til å bety "avslutning" eller "dump loggene dine" eller "skriv ut foo tusen ganger" eller hva som helst. Men jeg forstår ikke hvorfor de skal bruke dette vilkårlige navnet. Hvorfor ikke drepe -UPGRADE, eller drepe -GRACEFUL_SHUTDOWN? Har Unix bare visse signaler?
Mens vi gjør dette, bruker Nginx også følgende signaler (se dokumentasjon):
- TERM, INT: rask avstengning
- SLUTTE: grasiøs nedleggelse
- HUP:
- Start konfigurasjonen på nytt
- Start nye arbeidsflyter med ny konfigurasjon
- Grasiøs nedleggelse av gamle arbeidsflyter
- USR1: åpne loggfiler
- USR2: oppdater kjørbare filer på farten
- VINSJ: grasiøs gjennomføring av arbeidsflyter
HUP? Vinsj? Hva er årsaken til disse navnene? Hvor kan jeg finne ut mer om dette?
6 svar
Signalene som er tilgjengelige i OS bestemmes av OS (vanligvis etter POSIX) - de er ikke "strenger", men heltallskonstanter med standard navn... USR1 og USR2 er to signaler som ikke har noen spesifikk betydning, beregnet for enhver vilkårlig bruk som en utvikler ønsker.
På din linux maskin les mann 7 signal for oversikt over signal og signalhåndtering.
Du kan overstyre betydningen av andre signaler hvis du er villig til å jobbe med operativsystemet ved å gi disse signalene som svar på hendelser. Du kan for eksempel få HUP til å stå for «reload configuration» – hvis du enten er sikker på at prosessen aldri vil henge (terminaltap), eller du er villig til å håndtere tilfeller der OS, ikke brukeren, sender HUP-signalet.
HUP egner seg ikke til frysing. Dette signalet sendes til en prosess hvis dens kontrollerende terminal når slutten av filen. I gamle dager var kontrollterminaler vanligvis koblet til serielle porter eventuelt via en modemlinje på telefonlinje... Hvis telefonforbindelsen har blitt reversert, lokalt modem vil senke Carrier Detect-linjen, som vil sende en kjernefilfullføringsrapport og overført signal SIGHUP.
WINCH er ikke egnet for å "skifte vinduet". Den sendes til en prosess hvis dens kontrollerende terminal endres størrelse. Av åpenbare grunner er terminaler som kan endres størrelse vanligvis pseudoterminaler, som til syvende og sist representeres av en terminalemulator som kjører i et vindusmiljø (som xterm).
Ettersom signalnavn er standardiserte (POSIX). Du kan skrive din egen kjørbare kill-type for å ta -UPGRADE hvis du vil og levere USR1-signalet, men standard kill som følger med UNIX gjenkjenner det ikke.
Alternativt kan du lage et alias, en funksjon eller et shell-skript for å gjøre oversettelsen for deg, for eksempel med et bash-alias:
Alias oppgradering = "kill -USR1"
Signal.h-headerfilen tilordner signalnavn til deres faktiske implementeringsavhengige verdier.
I WINCH-termer synes jeg dette er litt avskyelig. Dette er signalet som leveres til applikasjoner når størrelsen på vinduet endres (spesielt når det kontrollerende terminalvinduet endres).
Å bruke dette til å lukke arbeidertråder på en elegant måte, er ikke en god idé med mindre du kan garantere at prosessen aldri vil kjøre i terminalen. Jeg vet at det ville vært en myte om jeg kjørte applikasjonen og den bestemte seg for å avbryte alt arbeid under fly bare fordi jeg maksimerte vinduet :-)
Prøv kill -l og finn svaret selv:
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) SIGPIPE) SIGPIPE) 7MIGTER SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGCHLD 3SI) SIGWIG2) 3SI16) SIGWINCH) 3SI16) 3SI16) 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 44) SIGRTMIN + 14 4) SIGRTMIN + 12 47) SIGRTMIN + 13 48) SIGRTMIN + 14 49) SIGRTMIN + 15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-95) SIGRTMAX) 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
Et signal eller virtuelt avbrudd er en melding som systemet sender til en prosess, eller en prosess sender til en annen. Når prosessen mottar et signal, avbrytes utførelsen av prosessprogrammet, og kontrollen overføres til subrutinen (funksjonen) - signalbehandleren. Etter å ha utført signalbehandleren, fortsetter kjøringen av det avbrutt programmet fra punktet hvor det ble avbrutt.
Operativsystemet gir stort antall typer signaler, men de fleste av disse typene er reservert for systemformål - de er signaler som operativsystemet sender til en prosess. Det er imidlertid også signaler om at prosesser kan utveksles med hverandre.
Som standard er reaksjonen på de fleste signaler å avslutte prosessen som mottok signalet, det vil si at hvis prosessen mottar et signal som den ikke gir for behandling, avsluttes prosessen som mottar signalet. For de fleste typer signaler kan imidlertid en prosess installere en behandler dette signalet eller sett til å ignorere dette signalet.
Hvis prosessen er i en "frivillig" suspendert tilstand (forårsaket for eksempel av utførelsen av søvnsystemanropet), mottar søvnsystemet signalet "våkneprosessen fra dvale", uavhengig av hva signalet ble håndtert. samtalen avsluttes umiddelbart.
Signalbehandleren i prosessen ser ut som en funksjon med en prototype:
Tomrom funksjonsnavn(int sigtype);
Parameteren til denne funksjonen er signaltypen (den samme behandleren kan installeres for å behandle signaler av forskjellige typer).
Signalsystemanropet brukes til å stille inn signalbehandleren din, for å avbryte den eller sette den til å ignorere signalet.
Signalbehandlingsfunksjoner er normale funksjoner C, de har tilgang til alle globalt synlige variabler og funksjoner. Men siden vi ikke vet på hvilket tidspunkt i programkjøringen behandlerfunksjonen vil bli kalt, må vi være spesielt forsiktige når vi får tilgang til de globale datastrukturene fra denne funksjonen. For funksjoner som behandler tråder, er det en til viktig krav- gjeninntreden. Siden en signalbehandler kan kalles når som helst i programkjøringen (og under visse forhold, under behandlingen av ett signal, kan en annen signalbehandler kalles), må behandlerne bruke funksjoner som tilfredsstiller kravet om reentrancy, det vil si, de kan ringes på det tidspunktet, når de allerede er oppringt et annet sted i programmet. Kravet om reentrancy koker faktisk ned til at funksjonen ikke bruker noen globale ressurser, uten å ta seg av synkronisering av tilgang til disse ressursene. Noen I/O-funksjoner, inkludert printf (), er ikke reentrant. Dette betyr at utdata fra én printf () funksjon kan bli forstyrret av utdata fra en annen funksjon. Følgende er en liste over reentrant-funksjoner som er trygge å ringe fra signalbehandlere.
Liste over reentrant-funksjoner
posix_trace_event () | |||
timer_getoverrun () | |||
En prosess kan sende et signal til en hvilken som helst annen prosess hvis PID den kjenner ved å bruke drepesystemkallet (til tross for dets formidable navn, dreper ikke dette systemkallet nødvendigvis prosessen den er adressert til). I noen tilfeller må en prosess sende et signal til seg selv, dette kan gjøres ved å bruke heve-systemet.
Noen typer signaler
Signaltyper identifiseres med numeriske tall, men programmering bruker ofte de symbolske signalnavnene som er definert i system-inkluderingsfiler. Noen av de mest brukte signalnavnene er:
Dette signalet avslutter prosessen som mottok det. Dette er det eneste signalet som ikke kan ignoreres og ikke kan tildeles sin egen behandler. |
|
Dette signalet er en forespørsel om å avslutte prosessen. Å gi dette signalet inkluderer for eksempel kommandoen (ikke et systemanrop!) Kill. Det antas at prosessen som mottar dette signalet skal avsluttes, men prosessen kan velge å ignorere signalet eller tilordne sin egen behandler. |
|
Systemet sender dette signalet til den overordnede prosessen når noen av dens underordnede prosesser avsluttes. Standardresponsen på dette signalet er ignorer. Foreldreprosessen bryr seg kanskje ikke om å håndtere dette signalet, med mindre den ønsker å bruke det til å synkronisere utførelsen med den underordnede prosessen. |
|
Dette signalet brukes til å telle tidsintervaller. Prosessen kan stille inn et visst tidsintervall ved hjelp av alarm- eller setitimer-systemanrop, og etter angi intervall systemet vil sende et SIGALRM-signal til det. |
|
SIGUSR1 og SIGUSR2 |
|
Disse signalene er ikke reservert for noen systemoppdrag... Prosesser kan sende disse signalene til hverandre og tolke dem etter eget ønske. |
For flere detaljer om signaltyper, se funksjonsbeskrivelsen