Sistema eragileak: Hiru pieza errazak. 3. zatia: Prozesuaren APIa (itzulpena)

Sistema Eragileen Sarrera

Aupa Habr! Nire ustez, literatura interesgarri baten artikulu-itzulpen sorta bat ekarri nahi dizuet - OSTEP. Material honek unix antzeko sistema eragileen lana sakonki eztabaidatzen du, hots, sistema eragile modernoa osatzen duten prozesuekin, hainbat programatzailerekin, memoriarekin eta antzeko beste osagaiekin lan egitea. Material guztien jatorrizkoa hemen ikus dezakezu Hemen. Kontuan izan itzulpena modu profesionalik gabe egin dela (nahiko askatasunez), baina espero dut esanahi orokorra mantendu dudala.

Gai honi buruzko laborategiko lanak hemen aurki daitezke:

Beste zati batzuk:

Nire kanala ere ikus dezakezu hemen telegrama =)

Alarma! Hitzaldi honetarako laborategi bat dago! Begira github

Prozesuaren APIa

Ikus dezagun UNIX sistema batean prozesu bat sortzeko adibide bat. Bi sistema-deien bidez gertatzen da sardexka () ΠΈ exec().

Deitu sardexka()

Sistema eragileak: Hiru pieza errazak. 3. zatia: Prozesuaren APIa (itzulpena)

Demagun fork() deia egiten duen programa bat. Bere exekuzioaren emaitza honakoa izango da.

Sistema eragileak: Hiru pieza errazak. 3. zatia: Prozesuaren APIa (itzulpena)

Lehenik eta behin, main() funtzioa sartu eta katea pantailan inprimatuko dugu. Lerroak jatorrizkoan deitzen den prozesu-identifikatzailea dauka PID edo prozesu-identifikatzailea. Identifikatzaile hau UNIXen erabiltzen da prozesu bati erreferentzia egiteko. Hurrengo komandoak fork() deituko du. Une honetan, prozesuaren kopia ia zehatza sortzen da. OSrako, badirudi programa beraren 2 kopia daudela sisteman exekutatzen, eta horrek fork() funtziotik irtengo dira. Sortu berria den prozesu seme-alaba (sortu duen prozesu nagusiaren aldean) ez da gehiago exekutatuko, main() funtziotik hasita. Gogoratu behar da prozesu seme-alaba ez dela prozesu nagusiaren kopia zehatza; bereziki, bere helbide-espazioa, bere erregistroak, instrukzio exekutagarrietarako erakuslea eta antzekoak ditu. Horrela, fork() funtzioaren deitzaileari itzultzen zaion balioa ezberdina izango da. Hain zuzen ere, guraso-prozesuak haurraren prozesuaren PID balioa jasoko du itzulera gisa, eta haurrak 0-ren balio bat jasoko du. Itzulpen-kode hauek erabiliz gero, prozesuak bereiz ditzakezu eta haietako bakoitza bere lana egitera behartu. . Hala ere, programa honen exekuzioa ez dago zorrozki definituta. 2 prozesutan banatu ondoren, sistema eragilea haien jarraipena egiten hasten da, baita haien lana planifikatzen ere. Nukleo bakarreko prozesadore batean exekutatzen bada, prozesuetako batek, kasu honetan gurasoak, lanean jarraituko du, eta, ondoren, prozesu umeak kontrola jasoko du. Berrabiaraztean, egoera ezberdina izan daiteke.

Deitu itxaron()

Sistema eragileak: Hiru pieza errazak. 3. zatia: Prozesuaren APIa (itzulpena)

Demagun hurrengo programa. Programa honetan, dei bat egoteagatik itxaron() Guraso-prozesua ume-prozesua amaitu arte itxarongo du beti. Kasu honetan, zorrozki definitutako testu irteera bat jasoko dugu pantailan

Sistema eragileak: Hiru pieza errazak. 3. zatia: Prozesuaren APIa (itzulpena)

exec() deitu

Sistema eragileak: Hiru pieza errazak. 3. zatia: Prozesuaren APIa (itzulpena)

Demagun erronka exec(). Sistema-dei hau erabilgarria da guztiz bestelako programa bat exekutatu nahi dugunean. Hemen deituko dugu execvp() hitzak zenbatzeko programa den wc programa exekutatzeko. Zer gertatzen da exec() deitzen denean? Dei honi fitxategi exekutagarriaren izena eta parametro batzuk argumentu gisa pasatzen zaizkio. Horren ostean, fitxategi exekutagarri honetako kodea eta datu estatikoak kargatzen dira eta kodearekin bere segmentua gainidazten da. Gainerako memoria-eremuak, hala nola pila eta heap, berriro hasten dira. Horren ondoren, sistema eragileak programa exekutatzen du, argumentu multzo bat pasatuz. Beraz, ez dugu prozesu berririk sortu, unean martxan dagoen programa beste programa batean eraldatu besterik ez dugu egin. Ondorengoan exec() deia exekutatu ondoren, jatorrizko programa batere exekutatu ez balitz bezala dirudi.

Abiarazteko konplikazio hau guztiz normala da Unix shell batentzat, eta shell horri kodea exekutatzea ahalbidetzen dio deitu ondoren sardexka (), baina deialdiaren aurretik exec(). Kode horren adibide bat abiarazi baino lehen shell ingurunea abiarazten ari den programaren beharretara doitzea izango litzateke.

Shell - Erabiltzaile programa bat besterik ez. Gonbidapen-lerroa erakusten dizu eta bertan zerbait idazteko zain dago. Gehienetan, programa baten izena bertan idazten baduzu, shell-ak bere kokapena aurkituko du, fork() metodoari deituko dio eta, ondoren, exec() mota bati deituko dio prozesu berri bat sortzeko eta amaitu arte itxarongo itxaron() deitu. Haurraren prozesua irteten denean, shell-a wait() deitik itzuliko da eta gonbita berriro inprimatuko du eta hurrengo komandoa sartu arte itxarongo da.

Fork() & exec() zatiketak shell-ak gauza hauek egiteko aukera ematen dio, adibidez:
wc fitxategia > fitxategi_berria.

Adibide honetan, wc programaren irteera fitxategi batera birbideratzen da. Shell-ak hori lortzeko modua nahiko sinplea da - deitu baino lehen prozesu ume bat sortuz exec(), shell-ak irteera estandarra ixten du eta fitxategia irekitzen du fitxategi_berria, beraz, exekutatzen ari den programaren irteera guztia wc pantaila batera ordez fitxategi batera birbideratuko da.

Unix kanalizazioa antzera inplementatzen dira, pipe() deia erabiltzen dutelako aldearekin. Kasu honetan, prozesuaren irteera-korrontea nukleoan kokatutako kanalizazio-ilara batera konektatuko da, eta beste prozesu baten sarrera-korrontea konektatuko da.

Iturria: www.habr.com

Gehitu iruzkin berria