2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Signaali (signaali) on ohjelmistokeskeytys. Se on tapa lähettää viestejä prosessien välillä. Sitä käytetään ilmoittamaan prosessille tapahtumasta, mutta se ei voi välittää prosessille mitään.
On monia syitä, miksi signaaleja syntyy Shellissä, voit käyttääkill
jakillall
Komento lähettää signaali:
kill -信号的类型 进程编号
killall -信号的类型 进程名
signaalin nimi | signaalin arvo | Oletuskäsittelytoiminto | Signaalin syy |
---|---|---|---|
HUOKAA | 1 | A | Pääte jumiutuu tai ohjausprosessi päättyy |
SIGINT | 2 | A | Näppäimistön keskeytys Ctrl+c |
SIGQUIT | 3 | C | Näppäimistön estonäppäintä painetaan |
SIGILL | 4 | C | Laiton ohje |
SIGTRAP | 5 | C | keskeytyskohdan ohjeet |
SIGABRT | 6 | C | Keskeytyssignaali, jonka on antanut abort(3) |
SIGBUS | 7 | C | väylävirhe |
SIGFPE | 8 | C | liukulukupoikkeus |
SIGKILL | 9 | A | kill -9 tappaa prosessin, tätä signaalia ei voida ottaa kiinni eikä jättää huomiotta |
SIGUSR1 | 10 | A | Käyttäjän määrittelemä signaali 1 |
SIGSEGV | 11 | C | Virheellinen muistiviittaus (matriisi rajojen ulkopuolella, nollaosoittimen toiminta) |
SIGUSR2 | 12 | A | Käyttäjän määrittelemä signaali 2 |
SIGPIPE | 13 | A | Kirjoita tiedot putkeen ilman lukuprosessia |
SIGALRM | 14 | A | Herätyskellon signaali, signaali lähetetään hälytys()-toiminnolla |
SIGTERM | 15 | A | Päätesignaali, oletusarvoisesti lähetetty signaali |
SIGSTKFLT | 16 | A | pinovirhe |
SIGCHLD | 17 | B | Lähetetään, kun lapsiprosessi päättyy |
SIGCONT | 18 | D | Jatka pysäytettyä prosessia |
SIGSTOP | 19 | D | Pysäytä prosessi |
SIGTSTP | 20 | D | Pääte paina stop-näppäintä |
SIGTTIN | 21 | D | Taustaprosessi pyytää terminaalin lukemista |
SIGTTOU | 22 | D | Taustaprosessi pyytää kirjoittamaan terminaaliin |
SIGURG | 23 | B | Hätätilan tunnistus (pistorasiat) |
SIGXCPU | 24 | C | Suorittimen aikaraja ylitetty |
SIGXFSZ | 25 | C | Tiedoston kokorajoitus ylitetty |
SIGVTALRM | 26 | A | virtuaalisen kellon signaali |
SIGPROF | 27 | A | Analysoi kellon signaaleja |
SIGWINCH | 28 | B | Ikkunan koko muuttuu |
SIGPOLL | 29 | B | Äänestys (Sys V) |
SIGPWR | 30 | A | sähkökatkos |
SIGSYS | 31 | C | Laiton järjestelmäpuhelu |
A:n oletustoiminto on lopettaa prosessi.
B:n oletustoiminto on jättää tämä signaali huomioimatta.
C:n oletustoiminto on lopettaa prosessi ja tehdä ytimen kuvavedos.
D:n oletustoiminto on pysäyttää prosessi, ja pysäytettyyn tilaan siirtyvä ohjelma voi jatkaa suorittamista.
Prosesseilla on kolme tapaa käsitellä signaaleja:
signal()
Toiminnot voivat määrittää, miten ohjelma käsittelee signaaleja.
Toimintoilmoitus:
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
Parametrin kuvaus:
sig
:Määritä siepattava signaali.func
: Osoitin signaalinkäsittelytoimintoon. Käsittelyfunktion on vastaanotettava kokonaislukuparametri, joka on siepatun signaalin numero.SIG_DFL
:SIG_DFL-makro edustaa oletussignaalinkäsittelymenetelmää.käyttääSIG_DFL
kutensignal
Toiminnon toinen parametri osoittaa, että signaalille käytetään järjestelmän oletuskäsittelymenetelmää.SIG_IGN
:SIG_IGN-makro tarkoittaa signaalin huomioimista.käyttääSIG_IGN
kutensignal
Toiminnon toinen parametri osoittaa, että kun prosessi vastaanottaa signaalin, se jättää sen huomioimatta eikä suorita mitään käsittelyä. Tämä voi estää prosessien odottamattoman päätymisen tai keskeytymisen tietyissä olosuhteissa.SIG_ERR
:SIG_ERR
Makroja käytetään osoittamaan virheitä.se ei ole kuinsignal
Toiminnon toista parametria käytetään sen sijaan assignal
Toiminnon palautusarvo osoittaa, että puhelu epäonnistui.jossignal
Jos funktion kutsu epäonnistuu, se palaaSIG_ERR
.Tätä käytetään yleensä havaitsemiseen ja käsittelyynsignal
Virhe toimintokutsussa.Palveluohjelma toimii taustalla Jos sen halutaan pysäyttää, sen tappaminen ei ole hyvä idea, koska kun prosessi lopetetaan, se kuolee yhtäkkiä eikä jälkityötä järjestetä.
Jos lähetät signaalin palveluohjelmalle, palveluohjelma kutsuu signaalin vastaanotettuaan funktion ja kirjoittaa toimintoon jälkikoodin ja ohjelma voi poistua suunnitellusti.
Lähettämällä 0-signaalin palveluohjelmalle voidaan havaita, onko ohjelma elossa.
Linux-käyttöjärjestelmä tarjoaa kill
jakillall
Komento lähettää ohjelmalle signaalin Ohjelmassa voit käyttääkill()
Kirjastotoiminnot lähettävät signaaleja muille prosesseille.
Toimintoilmoitus:
int kill(pid_t pid, int sig);
kill()
Funktio ottaa parametritsig
Määritetty signaali välitetään parametrillepid
määritelty prosessi.
parametri pid
On olemassa useita tilanteita:
pid > 0
Välitä signaali prosessille muodossapid
käsitellä asiaa.pid = 0
Välitä signaali kaikille prosesseille samassa prosessiryhmässä kuin nykyinen prosessi. Sitä käytetään usein lähettämään signaaleja aliprosessille.pid < -1
Välitä signaali prosessiryhmän ID:lle|pid|
kaikista prosesseista.pid = -1
Välittää signaalin kaikille prosesseille, joilla on lupa lähettää signaali, mutta ei prosessille, joka lähetti signaalin.Prosessin lopettamiseen on 8 tapaa, joista 5 on normaaleja lopetuksia, ne ovat:
main()
Toimintoja vartenreturn
palata;exit()
toiminto;_exit()
tai_Exit()
toiminto;return
palata;pthread_exit()
palata;On kolme tapaa lopettaa epänormaalisti, ne ovat:
abort()
toiminto keskeyttää;olla olemassa main()
Toiminnossa,return
Palautettu arvo on lopetustila, jos eireturn
lausunto tai soittoexit()
, niin prosessin lopetustila on 0.
Tarkastele kuoressa prosessin lopettamisen tilaa:
echo $?
3 toimintoa prosessin päättämiseksi normaalisti (exit()
ja_Exit()
on määritelty ISO C:ssä,_exit()
on POSIX:n määrittelemä):
void exit(int status);
void _exit(int status);
void _Exit(int status);
status
Prosessin lopettamisen tila.
return
Osoittaa, että kun funktio palaa, paikallisen objektin tuhoajaa kutsutaan.main()
toiminnassareturn
Globaalin objektin tuhoajaa kutsutaan myös.exit()
Ilmaisee prosessin lopettamisen, paikallisen objektin tuhoajaa ei kutsuta, vain globaalin objektin tuhoajaa kutsutaan._exit()
ja_Exit()
Poistu suoraan, eikä siivousta suoriteta.Prosessi on käytettävissä atexit()
Toimintojen rekisteröinti lopettaa toiminnot (32 asti), nämä toiminnot ovatexit()
Soitetaan automaattisesti.
int atexit(void (*function)(void));
exit()
Lopetustoimintojen kutsun järjestys on käänteinen rekisteröintihetkestä lähtien.
system()
Funktio tarjoaa yksinkertaisen menetelmän ohjelman suorittamiseen välittäen ohjelman ja suoritettavat parametrit merkkijonona.system()
Pelkkää toimintaa.
Toimintoilmoitus:
int system(const char * string);
system()
Toiminnon palautusarvo on hankalampi.
system()
Funktio palauttaa nollasta poikkeavan;system()
Funktio palauttaa 0;system()
Funktio palauttaa nollasta poikkeavan.exec
Funktioperheet tarjoavat toisen tavan kutsua ohjelmia (binäärejä tai komentosarjoja) prosessin sisällä.
exec
Toimintoperhe ilmoitetaan seuraavasti:
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
Ilmoitus:
errno
keskellä.exec
Tämän jälkeen kutsuttu ohjelma korvaa kutsuvan ohjelman, eliexec
Ei koodia toiminnon suorittamisen jälkeen.execl()
jaexecv()
, muita käytetään harvoin.Kaikki prosessit koko Linux-järjestelmässä ovat puurakenteessa.
käyttääpstree
Voit tarkastella prosessipuuta komennolla:
pstree -p 进程编号
Jokaisella prosessilla on yksilöllinen prosessitunnus, jota edustaa ei-negatiivinen kokonaisluku. Vaikka prosessitunnukset ovat ainutlaatuisia, niitä voidaan käyttää uudelleen. Kun prosessi päättyy, sen prosessitunnuksesta tulee ehdokas uudelleenkäyttöön. Linux käyttää viivästettyä uudelleenkäyttöalgoritmia, jotta juuri luodun prosessin tunnus eroaa äskettäin lopetetun prosessin käyttämästä ID:stä. Tämä estää sitä, että uusia prosesseja erehtyisivät erehtymään samaa tunnusta käyttäviksi lopetetuiksi prosesseiksi.
Toiminto prosessitunnuksen saamiseksi:
pid_t getpid(void); // 获取当前进程的ID。
pid_t getppid(void); // 获取父进程的ID。
Olemassa oleva prosessi voi kutsuafork()
Toiminto luo uuden prosessin.
Toimintoilmoitus:
pid_t fork(void);
Riippuafork()
Luotua uutta prosessia kutsutaan lapsiprosessiksi.
fork()
Funktiota kutsutaan kerran, mutta se palaa kahdesti. Ero näiden kahden palautuksen välillä on, että aliprosessin palautusarvo on 0, kun taas pääprosessin palautusarvo on juuri luodun aliprosessin prosessitunnus.
Lapsiprosessi ja emoprosessi jatkuvatfork()
Koodi sen jälkeen, Aliprosessi on kopio pääprosessista. Aliprosessilla on kopio ylätason prosessin tietotilasta, keosta ja pinosta (huomaa: aliprosessi omistaa kopion, ei jaeta pääprosessin kanssa).
fork()
Sen jälkeen ylä- ja alatason prosessien suoritusjärjestys on määrittelemätön.
fork()
, anna aliprosessin käsitellä nämä pyynnöt, kun taas pääprosessi odottaa seuraavaa yhteyspyyntöä.fork()
Soitettiin heti paluun jälkeenexec
。fork()
Yksi ominaisuus on, että pääprosessissa avatut tiedostokuvaukset kopioidaan aliprosessiin, ja pääprosessilla ja aliprosessilla on sama tiedostosiirtymä.
Jos pääprosessi ja aliprosessi kirjoittavat saman kuvaajan osoittamaan tiedostoon ilman minkäänlaista synkronointia, niiden tulosteet voivat sekoittua keskenään.
Tässä vaiheessa näet, että tietoja on vain 100 000 riviä.
Tällä hetkellä dataa pitäisi olla 200 000 riviä vähemmän, koska tiedoston kirjoitustoiminto ei ole atomi. Synkronointimekanismin puuttuessa kaksi prosessia voi yrittää kirjoittaa tiedoston eri osia samanaikaisesti kirjoitus epäonnistuu.
vfork()
Toimintokutsut ja palautusarvot ovat samat kuinfork()
Sama, mutta niiden semantiikka on erilainen.
vfork()
Funktiolla luodaan uusi prosessi, jonka tarkoitus onexec
Uusi ohjelma, joka ei kopioi pääprosessin osoiteavaruutta, koska aliprosessi kutsuu välittömästiexec
, joten pääprosessin osoiteavaruutta ei käytetä. Jos aliprosessi käyttää emoprosessin osoiteavaruutta, voi ilmetä tuntemattomia tuloksia.
vfork()
jafork()
Toinen ero on:vfork()
Varmista, että aliprosessi suoritetaan ensin, ja kutsu se aliprosessissaexec
taiexit
Sen jälkeen emoprosessi jatkaa toimintaansa.
Käyttöjärjestelmässä zombie-prosessi viittaa aliprosessiin, joka on päättynyt, mutta sen pääprosessi ei ole vielä lukenut poistumistilaa. Vaikka zombie-prosessi ei ole enää käynnissä, sillä on silti merkintä prosessitaulukossa, jotta ydin voi tallentaa prosessin poistumistilatiedot (kuten prosessin tunnuksen, poistumistilan jne.), kunnes pääprosessi lukee nämä tiedot.
Jos pääprosessi poistuu ennen aliprosessia, aliprosessia isännöi prosessi 1 (tämä on myös tapa antaa prosessin suorittaa taustalla).
Jos aliprosessi poistuu ennen emoprosessia, eikä pääprosessi käsittele aliprosessin poistumistietoja, aliprosessista tulee zombieprosessi.
Ydin säilyttää tietorakenteen jokaiselle aliprosessille, mukaan lukien prosessin numero, lopetustila, käytetty CPU-aika jne. Jos pääprosessi käsittelee aliprosessin poistumistiedot, ydin vapauttaa tämän tietorakenteen. Jos pääprosessi ei käsittele aliprosessin poistumistietoja, ydin ei vapauta tätä tietorakennetta ja aliprosessin prosessinumero on aina varattu. Järjestelmässä käytettävissä olevat prosessimäärät ovat rajalliset. Jos zombie-prosesseja syntyy suuri määrä, järjestelmä ei pysty generoimaan uusia prosesseja, koska käytettävissä ei ole prosessinumeroita.
signal(SIGCHLD, SIG_IGN)
Ilmoita ytimelle, että se ei ole kiinnostunut lapsiprosessin poistumisesta, ja sen tietorakenne vapautetaan heti aliprosessin poistuttua.wait()
/waitpid()
toiminto: Pääprosessi odottaa aliprosessin päättymistä kutsumalla näitä toimintoja ja saa sen poistumistilan vapauttaen siten aliprosessin käyttämät resurssit.pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
pid_t wait3(int *status, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
Palautusarvo on aliprosessin numero.
stat_loc
Onko tiedot lapsiprosessin lopettamisesta:
a) Jos lopetetaan normaalisti, makro WIFEXITED(stat_loc)
Palaa tosi, makroWEXITSTATUS(stat_loc)
Irtisanomisen tila voidaan saada;
b) Jos se päättyy epänormaalisti, makro WTERMSIG(stat_loc)
Saa signaalin prosessin lopettamiseksi.
Jos vanhempi prosessi on varattu, voit kaapata SIGCHLD
Signaali, kutsutaan signaalinkäsittelytoiminnossawait()
/waitpid()
。
[Lähetä signaaleja prosessien välillä](##1.5 Lähetä signaaleja)
Moniprosessipalveluohjelmassa, jos aliprosessi vastaanottaa poistumissignaalin, aliprosessi poistuu itsestään.
Jos pääprosessi vastaanottaa poistumissignaalin, sen tulee lähettää poistumissignaalit kaikille lapsiprosesseille ja sitten poistua itse.
Monisäikeet jakavat prosessin osoiteavaruuden,Jos useiden säikeiden on käytettävä samaa muistia, käytä vain yleisiä muuttujia.。
Useissa prosesseissa kunkin prosessin osoiteavaruus on itsenäinen eikä jaettu.Jos useiden prosessien on käytettävä samaa muistia, globaaleja muuttujia ei voida käyttää, vain jaettua muistia voidaan käyttää.。
Jaettu muisti sallii useiden prosessien pääsyn samaan muistitilaan (prosessien välillä ei vaadita verisuhdetta). Se on tehokkain tapa jakaa ja siirtää tietoja useiden prosessien välillä. Prosessit voivat yhdistää jaetun muistin omaan osoiteavaruuteensa. Jos yksi prosessi muuttaa jaetussa muistissa olevia tietoja, myös muiden prosessien lukemat tiedot muuttuvat.
Jaettu muisti ei tarjoa lukitusmekanismia, eli kun prosessi lukee/kirjoittaa jaettua muistia, se ei estä muita prosesseja lukemasta/kirjoittamasta sitä.Jos haluat lukita jaetun muistin luku-/kirjoitustoiminnon, voit käyttää semaforia . Linux tarjoaa joukon toimintoja jaetun muistin käyttöä varten.
Tätä toimintoa käytetään jaetun muistin luomiseen/hankimiseen.
int shmget(key_t key, size_t size, int shmflg);
typedef unsigned int key_t
), yleensä esimerkiksi heksadesimaalimuodossa 0x5005
, eri yhteisten muistojen avaimet eivät voi olla samat.0666|IPC_CREAT
Ilmaisee, että jos jaettua muistia ei ole, luo se.käyttää ipcs -m
Voit tarkastella järjestelmän jaettua muistia, mukaan lukien: avain, jaetun muistin tunnus (shmid), omistaja, käyttöoikeudet (perms) ja koko (tavuja).
käyttää ipcrm -m 共享内存id
Jaettu muisti voidaan poistaa manuaalisesti seuraavasti:
Huomautus: Säilöjä ei voi käyttää jaetun muistin tietotyypeille, vain perustietotyyppejä voidaan käyttää.
Tätä toimintoa käytetään yhdistämään jaettu muisti nykyisen prosessin osoiteavaruuteen.
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmget()
Toiminnon palauttama jaetun muistin tunniste.Palauttaa jaetun muistin aloitusosoitteen, kun puhelu on onnistunut, ja palauttaa, kun se epäonnistuu. (void *)-1
。
Tätä toimintoa käytetään irrottamaan jaettu muisti nykyisestä prosessista, joka vastaa shmat()
Funktion käänteinen toiminta.
int shmdt(const void *shmaddr);
shmat()
Toiminnon palauttama osoite.Palauttaa 0, jos puhelu onnistuu ja -1, jos se epäonnistuu.
Tätä toimintoa käytetään jaetun muistin käyttämiseen. Yleisin toiminto on jaetun muistin poistaminen.
int shmctl(int shmid, int command, struct shmid_ds *buf);
shmget()
Toiminnon palauttama jaetun muistin tunnus.IPC_RMID
。Palauttaa 0, jos puhelu onnistuu ja -1, jos se epäonnistuu.
Huomaa, käytä root
Tavalliset käyttäjät eivät voi poistaa luotua jaettua muistia luoduista käyttöoikeuksista huolimatta.
Palauttaa 0, jos puhelu onnistuu ja -1, jos se epäonnistuu.
Tätä toimintoa käytetään jaetun muistin käyttämiseen. Yleisin toiminto on jaetun muistin poistaminen.
int shmctl(int shmid, int command, struct shmid_ds *buf);
shmget()
Toiminnon palauttama jaetun muistin tunnus.IPC_RMID
。Palauttaa 0, jos puhelu onnistuu ja -1, jos se epäonnistuu.
Huomaa, käytä root
Tavalliset käyttäjät eivät voi poistaa luotua jaettua muistia luoduista käyttöoikeuksista huolimatta.
[Ulkoisten linkkien kuvia siirretään...(img-v6qW3XRA-1720711279572)]
[Ulkoisten linkkien kuvia siirretään...(img-CG0tGAne-1720711279572)]