Operaciumoj: Tri Facilaj Pecoj. Parto 3: Proceza API (traduko)

Enkonduko al Operaciumoj

Hej Habr! Mi ŝatus atentigi vin serion da artikoloj-tradukoj de unu interesa literaturo laŭ mi - OSTEP. Ĉi tiu materialo diskutas sufiĉe profunde la laboron de Unikso-similaj operaciumoj, nome, laboro kun procezoj, diversaj planiloj, memoro kaj aliaj similaj komponantoj kiuj konsistigas modernan OS. Vi povas vidi la originalon de ĉiuj materialoj ĉi tie tie. Bonvolu noti, ke la traduko estis farita senprofesie (sufiĉe libere), sed mi esperas, ke mi konservis la ĝeneralan signifon.

Laboratorio pri ĉi tiu temo troveblas ĉi tie:

Aliaj partoj:

Vi ankaŭ povas kontroli mian kanalon ĉe telegramo =)

Alarmo! Estas laboratorio por ĉi tiu prelego! Rigardu github

Proceza API

Ni rigardu ekzemplon pri kreado de procezo en UNIX-sistemo. Ĝi okazas per du sistemvokoj forko () и exec ().

Voku forkon ()

Operaciumoj: Tri Facilaj Pecoj. Parto 3: Proceza API (traduko)

Konsideru programon, kiu faras fork() vokon. La rezulto de ĝia ekzekuto estos kiel sekvas.

Operaciumoj: Tri Facilaj Pecoj. Parto 3: Proceza API (traduko)

Antaŭ ĉio, ni eniras la funkcion main() kaj presas la ĉenon al la ekrano. La linio enhavas la procezidentigilon kiu en la originalo estas nomita PID aŭ procezidentigilo. Ĉi tiu identigilo estas uzata en UNIX por rilati al procezo. La sekva komando vokos fork(). Je ĉi tiu punkto, preskaŭ preciza kopio de la procezo estas kreita. Por la OS, ŝajnas, ke ekzistas 2 kopioj de la sama programo funkcianta en la sistemo, kiu siavice eliros la funkcion fork(). La nove kreita infanprocezo (rilate al la gepatra procezo kiu kreis ĝin) ne plu estos ekzekutita, komencante de la funkcio main(). Oni devas memori, ke infana procezo ne estas ekzakta kopio de la gepatra procezo; precipe, ĝi havas sian propran adresspacon, siajn proprajn registrojn, sian propran montrilon al plenumeblaj instrukcioj, kaj simile. Tiel, la valoro redonita al la alvokanto de la funkcio fork() estos malsama. Aparte, la gepatra procezo ricevos la PID-valoron de la infana procezo kiel revenon, kaj la infano ricevos valoron egala al 0. Uzante ĉi tiujn revenkodojn, vi povas tiam apartigi procezojn kaj devigi ĉiun el ili fari sian propran laboron. . Tamen, la ekzekuto de ĉi tiu programo ne estas strikte difinita. Post dividiĝo en 2 procezojn, la OS komencas kontroli ilin, kaj ankaŭ plani ilian laboron. Se ekzekutita sur unukerna procesoro, unu el la procezoj, en ĉi tiu kazo la gepatro, daŭre funkcios, kaj tiam la infana procezo ricevos kontrolon. Dum rekomenco, la situacio povas esti malsama.

Voku atendi()

Operaciumoj: Tri Facilaj Pecoj. Parto 3: Proceza API (traduko)

Konsideru la sekvan programon. En ĉi tiu programo, pro la ĉeesto de voko atendi () La gepatra procezo ĉiam atendos ke la infana procezo finiĝos. En ĉi tiu kazo, ni ricevos strikte difinitan tekstan eligon sur la ekrano

Operaciumoj: Tri Facilaj Pecoj. Parto 3: Proceza API (traduko)

exec() voko

Operaciumoj: Tri Facilaj Pecoj. Parto 3: Proceza API (traduko)

Konsideru la defion exec (). Ĉi tiu sistemvoko estas utila kiam ni volas ruli tute alian programon. Ĉi tie ni vokos execvp () ruli la programon wc kiu estas vortkalkula programo. Kio okazas kiam exec() estas vokita? Ĉi tiu alvoko estas pasigita la nomo de la plenumebla dosiero kaj iuj parametroj kiel argumentoj. Post tio la kodo kaj senmovaj datumoj de ĉi tiu rulebla dosiero estas ŝarĝitaj kaj ĝia propra segmento kun la kodo estas anstataŭita. La ceteraj memorareoj, kiel ekzemple la stako kaj amaso, estas rekomencigitaj. Post tio la OS simple ekzekutas la programon, pasigante al ĝi aron da argumentoj. Do ni ne kreis novan procezon, ni simple transformis la nun kurantan programon en alian kurantan programon. Post ekzekuto de la exec()-voko en la posteulo, ŝajnas kvazaŭ la origina programo tute ne funkciis.

Ĉi tiu startkomplikaĵo estas tute normala por Unikso-simila ŝelo, kaj permesas al tiu ŝelo ekzekuti kodon post vokado forko (), sed antaŭ la voko exec (). Ekzemplo de tia kodo estus alĝustigi la ŝelan medion al la bezonoj de la lanĉa programo, antaŭ ol lanĉi ĝin.

ŝelo - nur uzanta programo. Ŝi montras al vi la invitlinion kaj atendas ke vi skribu ion en ĝi. Plejofte, se vi skribas la nomon de programo tie, la ŝelo trovos ĝian lokon, vokos la fork()-metodon, kaj poste vokos iun tipon de exec() por krei novan procezon kaj atendos, ke ĝi finiĝos uzante wait() voko. Kiam la infana procezo eliras, la ŝelo revenos de la alvoko wait() kaj presis la prompton denove kaj atendos la sekvan komandon por esti enigita.

La fork() & exec()-dividado permesas al la ŝelo fari la jenajn aferojn, ekzemple:
wc dosiero > nova_dosiero.

En ĉi tiu ekzemplo, la eligo de la wc-programo estas redirektita al dosiero. La maniero kiel la ŝelo atingas tion estas sufiĉe simpla - kreante infanan procezon antaŭ vokado exec (), la ŝelo fermas norman eligon kaj malfermas la dosieron nova_dosiero, tiel, ĉio eligo de la plua funkcianta programo wc estos redirektita al dosiero anstataŭ al ekrano.

Pipo Unikso estas efektivigitaj en simila maniero, kun la diferenco ke ili uzas pipe() vokon. En ĉi tiu kazo, la eligfluo de la procezo estos konektita al pipvico situanta en la kerno, al kiu la eniga fluo de alia procezo estos konektita.

fonto: www.habr.com

Aldoni komenton