Signaler i linux. Eksempler. Sender signaler fra tastaturet. Signaler og systemanrop

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:

  1. SA_NOCLDSTOP - send SIGCHLD-signal bare hvis underordnet prosessen blir avbrutt. Å stanse en underordnet prosess fører ikke til at et signal sendes.
  2. SA_NODEFER - emulering av enkle (upålitelige) signaler.
  3. SA_RESTHAND - etter at et signal ankommer, tilbakestilles dets behandler til SIG_DFL.
  4. 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:

  1. SIG_BLOCK - signaler fra settet er blokkert;
  2. SIG_UNBLOCK - signaler fra settet er blokkert;
  3. 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 Systemoverskriftsfil. De er vanligvis forkortet uten SIG-prefikset; for eksempel blir SIGHUP ofte referert til som HUP.

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.
Funksjonene knyttet til disse tastekombinasjonene kan tilordnes andre taster ved hjelp av stty-kommandoen, men i praksis er dette svært sjeldent. Vi antar at disse tastene har sine standardfunksjoner knyttet til seg. Når et signal kommer, er ett av to scenarier mulig. Hvis en prosess har tildelt en prosesseringsrutine til et signal, vil den etter anropet forsynes med informasjon om konteksten signalet ble generert i. Ellers utfører kjernen standardhandlinger på vegne av prosessen. Disse handlingene avhenger av signalet. Mange signaler fører til avslutning av prosessen, og i noen tilfeller genereres det også en minnedump. Prosedyren for å påkalle en behandler kalles signalavskjæring. Når behandleren er ferdig med å utføre, fortsetter prosessen fra punktet der signalet ble mottatt. For å forhindre at visse signaler kommer inn i programmet, må du angi at de skal ignoreres eller blokkeres. Det ignorerte signalet blir ganske enkelt sendt over og påvirker ikke driften av prosessen. Et blokkert signal står i kø for behandling, men kjernen krever ingen handling fra prosessen før signalet eksplisitt er opphevet. Behandleren kalles kun én gang for et ublokkert signal, selv om flere lignende signaler mottas i løpet av blokkeringsperioden. Nedenfor er signalene som bør være kjent for alle Systemadministrator... Tradisjonelt skrives signalnavn store bokstaver... Noen ganger er navn prefikset med SIG (for eksempel SIGHUP). Navn Beskrivelse Reaksjon Interceptions - Blocks - Dump som standard 1 HUP Legg på Slutt Ja Ja Nei 2 INT Avbryt Slutt Ja Ja Nei 3 AVSLUTT Avslutt Slutt Ja Ja Ja 9 KILL Kill End Nei Nei Nei 10 BUS Bussfeil Slutt Ja Ja Ja 11 SEGV Segmentering Feil Slutt Ja Ja Ja 12 TERM Slutt Forespørsel slutt Ja Ja Nei 13 STOPP Stopp Stopp Nei Nei Nei 14 TSTP Stoppsignal sendt Stopp Ja Ja Nei fra tastatur 15 FORTS Fortsett etter stopp Ignorert Ja Nei Nei 16 VINSJ Vinduendring Ignorert Ja Ja Nei 17 USR1 Brukerdefinert Fullføring Ja Ja Nei 18 USR2 Bruker -definert Fullføring Ja Ja Nei Det er andre signaler som ikke er vist i tabellen. 5,1; de fleste av dem rapporterer om alle slags kryptiske feil, som «feil instruksjon». Som standard har disse signalene en tendens til å avslutte programmet og lage en minnedump. Avlytting og blokkering av signaler er vanligvis tillatt, siden det er tilstrekkelig "smarte" programmer som eliminerer konsekvensene av feil. BUS- og segv-signaler sendes også når feil oppstår. Vi inkluderte dem i tabellen fordi de er ekstremt vanlige: de krasjer vanligvis på grunn av dem. I seg selv har disse signalene ingen diagnostisk verdi. De indikerer bare faktum om feil minnetilgang6. DREPE- og STOPP-signalene kan verken fanges opp, blokkeres eller ignoreres. KILL-signalet dreper prosessen som det sendes til, og STOP-signalet suspenderer utførelsen av prosessen inntil et CONT-signal mottas. CONT-signalet kan fanges opp og ignoreres, men ikke blokkeres. tstp-signalet er en mer fleksibel versjon av STOP-signalet. Det beskrives enklest som en stoppforespørsel. Den genereres av terminaldriveren når brukeren trykker på en tastekombinasjon ... Programmer som fanger dette signalet utfører vanligvis oppryddingsoperasjoner og sender deretter et STOPP-signal til seg selv. På den annen side kan programmer ignorere TSTP-signalet slik at de ikke kan stoppes av en tastaturkommando. Terminalemulatorer sender et WINCH-signal når det er en endring i konfigurasjonsparameterne deres (for eksempel antall linjer på en virtuell terminal). Dette tillater programmer som samhandler med emulatorer som f.eks tekstredigerere, automatisk rekonfigurere seg selv som svar på endringer. Hvis vinduet ikke kan endres på riktig måte, kontroller at WINCH-signalet genereres og behandles riktig. Mens hensikten med KILL, INT, TERM, HUP og QUIT-signalene kan virke det samme, er de i virkeligheten helt forskjellige.
  • 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.
USR1- og USR2-signalene har ingen standardformål. De kan brukes til ulike formål. For eksempel tolker Apache-nettserveren USR1-signalet som en omstartsforespørsel. Sende signaler: The kill Command Kill-kommandoen brukes oftest for å drepe prosesser. Denne kommandoen kan sende et hvilket som helst signal til prosessen, men som standard er det TERM-signalet. Kill-kommandoen kan utføres av både vanlige brukere (for deres egne prosesser) og superbrukeren (for enhver prosess). Den har følgende syntaks: kill [-signal] identifikator, der signal er nummeret eller det symbolske navnet på signalet som skal sendes, og identifikator er nummeret på prosessen det søkes etter. Kill-kommandoen uten et signalnummer garanterer ikke at prosessen vil bli drept, siden TERM-signalet kan fanges opp, blokkeres og ignoreres. Kommando drep -9 id"garantert" å drepe prosessen, siden signal 9 (KILL) ikke blir fanget opp. Bruk kill -9 kommandoen bare hvis en høflig programavslutningsforespørsel ikke er gjort. Vi skrev ordet "garantert" i anførselstegn, fordi noen ganger går prosesser inn i en tilstand der de ikke kan avsluttes selv på denne måten (vanligvis er dette på grunn av blokkering av I/O, for eksempel når de stopper hardisk). Den eneste utveien i denne situasjonen er å starte på nytt. Killall-kommandoen kjøres ulike funksjoner v UNIX-systemer og Linux. V Linux kommando killall dreper prosessene spesifisert av navnet. For eksempel dreper følgende kommando alle prosesser Apache webserver. ubuntu $ sudo killall httpd Standard UNIX killall kommando gitt i Solaris-, HP-UX- og AIX-distribusjoner, godtar ikke parametere og dreper ganske enkelt alle prosesser nåværende bruker... Å kjøre den som superbruker vil drepe init-prosessen og slå av datamaskinen. Wow! Pgrep og pkill kommandoer i Solaris-systemer, HP-UX og Linux (men ikke i AEX) søker etter prosesser, gitte navn(eller andre attributter). Kommandoen pgrep viser prosess-ID-ene som samsvarer med kriteriene som er spesifisert på kommandolinjen, og pkill-kommandoen sender et signal til prosessene som ble funnet. For eksempel sender følgende kommando TERM-signalet til alle prosesser som kjører som bruker ben. $ sudo pkill -u ben

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