logo

Tarpprocesinis ryšys (IPC)

Procesas gali būti dviejų tipų:

  • Nepriklausomas procesas.
  • Bendradarbiavimo procesas.

Nepriklausomo proceso neturi įtakos kitų procesų vykdymas, o bendradarbiaujantį procesą gali paveikti kiti vykdantys procesai. Nors galima manyti, kad tie procesai, kurie veikia savarankiškai, vyks labai efektyviai, iš tikrųjų yra daug situacijų, kai kooperatyvą galima panaudoti siekiant padidinti skaičiavimo greitį, patogumą ir moduliškumą. Inter-process communication (IPC) yra mechanizmas, leidžiantis procesams bendrauti tarpusavyje ir sinchronizuoti savo veiksmus. Šių procesų bendravimas gali būti vertinamas kaip jų bendradarbiavimo būdas. Procesai gali bendrauti vienas su kitu per abu:



  1. Bendra atmintis
  2. Pranešimo perdavimas

Toliau pateiktame 1 paveiksle parodyta pagrindinė komunikacijos tarp procesų, naudojant bendrosios atminties metodą ir pranešimų perdavimo metodą, struktūra.

Operacinė sistema gali įgyvendinti abu ryšio būdus. Pirmiausia aptarsime bendrosios atminties bendravimo būdus, o tada pranešimų perdavimą. Bendravimas tarp procesų naudojant bendrą atmintį reikalauja, kad procesai dalytųsi tam tikru kintamuoju, ir tai visiškai priklauso nuo to, kaip programuotojas tai įgyvendins. Vieną bendravimo būdą naudojant bendrą atmintį galima įsivaizduoti taip: Tarkime, kad procesas1 ir procesas2 vykdomi vienu metu ir jie dalijasi tam tikrais ištekliais arba naudoja informaciją iš kito proceso. Process1 generuoja informaciją apie tam tikrus naudojamus skaičiavimus arba išteklius ir saugo ją kaip įrašą bendrojoje atmintyje. Kai procesui2 reikia naudoti bendrinamą informaciją, jis patikrins bendrojoje atmintyje saugomą įrašą ir atsižvelgs į proceso1 sugeneruotą informaciją ir atitinkamai veiks. Procesai gali naudoti bendrinamą atmintį informacijai išgauti kaip įrašą iš kito proceso, taip pat bet kokiai konkrečiai informacijai pateikti kitiems procesams.
Aptarkime bendravimo tarp procesų, naudojant bendrosios atminties metodą, pavyzdį.



i) Bendrosios atminties metodas

Pvz.: gamintojo ir vartotojo problema
Yra du procesai: gamintojas ir vartotojas. Gamintojas gamina kai kuriuos daiktus, o Vartotojas tą prekę suvartoja. Abu procesai turi bendrą erdvę arba atminties vietą, vadinamą buferiu, kurioje saugoma gamintojo pagaminta prekė ir iš kurios vartotojas prireikus sunaudoja prekę. Yra dvi šios problemos versijos: pirmoji yra žinoma kaip neapriboto buferio problema, kai gamintojas gali tęsti gaminių gamybą, o buferio dydis neribojamas, antroji vadinama riboto buferio problema. kurią Gamintojas gali pagaminti iki tam tikro prekių skaičiaus prieš pradėdamas laukti, kol vartotojas jas suvartos. Aptarsime riboto buferio problemą. Pirma, gamintojas ir vartotojas turės bendrą atmintį, tada gamintojas pradės gaminti prekes. Jei bendras pagamintos prekės kiekis yra lygus buferio dydžiui, gamintojas lauks, kol ją sunaudos Vartotojas. Panašiai vartotojas pirmiausia patikrins, ar prekė yra prieinama. Jei prekės nėra, vartotojas lauks, kol Gamintojas ją pagamins. Jei yra prekių, vartotojas jas sunaudos. Toliau pateikiamas pseudokodas, skirtas parodyti:
Bendrinami duomenys tarp dviejų procesų

C






#define buff_max 25> #define mod %> >struct> item{> >// different member of the produced data> >// or consumed data> >---------> >}> > >// An array is needed for holding the items.> >// This is the shared place which will be> >// access by both process> >// item shared_buff [ buff_max ];> > >// Two variables which will keep track of> >// the indexes of the items produced by producer> >// and consumer The free index points to> >// the next free index. The full index points to> >// the first full index.> >int> free_index = 0;> >int> full_index = 0;> >

>

>

Gamintojo proceso kodas

C




item nextProduced;> > >while>(1){> > >// check if there is no space> >// for production.> >// if so keep waiting.> >while>((free_index+1) mod buff_max == full_index);> > >shared_buff[free_index] = nextProduced;> >free_index = (free_index + 1) mod buff_max;> >}>

>

>

Vartotojo proceso kodas

C




item nextConsumed;> > >while>(1){> > >// check if there is an available> >// item for consumption.> >// if not keep on waiting for> >// get them produced.> >while>((free_index == full_index);> > >nextConsumed = shared_buff[full_index];> >full_index = (full_index + 1) mod buff_max;> >}>

>

>

Aukščiau pateiktame kode gamintojas vėl pradės gaminti, kai (free_index+1) mod buff max bus nemokama, nes jei jis nėra nemokamas, tai reiškia, kad vis dar yra prekių, kurias vartotojas gali suvartoti, todėl nereikia gaminti daugiau. Panašiai, jei nemokamas indeksas ir visas indeksas nurodo tą patį indeksą, tai reiškia, kad nereikia vartoti prekių.

Bendras C++ įgyvendinimas:

C++




#include> #include> #include> #include> #define buff_max 25> #define mod %> struct> item {> >// different member of the produced data> >// or consumed data> >// ---------> };> // An array is needed for holding the items.> // This is the shared place which will be> // access by both process> // item shared_buff[buff_max];> // Two variables which will keep track of> // the indexes of the items produced by producer> // and consumer The free index points to> // the next free index. The full index points to> // the first full index.> std::atomic<>int>>free_index(0);> std::atomic<>int>>full_index(0);> std::mutex mtx;> void> producer() {> >item new_item;> >while> (>true>) {> >// Produce the item> >// ...> >std::this_thread::sleep_for(std::chrono::milliseconds(100));> >// Add the item to the buffer> >while> (((free_index + 1) mod buff_max) == full_index) {> >// Buffer is full, wait for consumer> >std::this_thread::sleep_for(std::chrono::milliseconds(100));> >}> >mtx.lock();> >// Add the item to the buffer> >// shared_buff[free_index] = new_item;> >free_index = (free_index + 1) mod buff_max;> >mtx.unlock();> >}> }> void> consumer() {> >item consumed_item;> >while> (>true>) {> >while> (free_index == full_index) {> >// Buffer is empty, wait for producer> >std::this_thread::sleep_for(std::chrono::milliseconds(100));> >}> >mtx.lock();> >// Consume the item from the buffer> >// consumed_item = shared_buff[full_index];> >full_index = (full_index + 1) mod buff_max;> >mtx.unlock();> >// Consume the item> >// ...> >std::this_thread::sleep_for(std::chrono::milliseconds(100));> >}> }> int> main() {> >// Create producer and consumer threads> >std::vectorthread>siūlai; gijos.emplace_back(gamintojas); gijos.emplace_back(vartotojas); // Palaukite, kol gijos baigsis (automatinis& gijos : gijos) { thread.join(); } grąžinti 0; }>

>

>

java pseudokodas

Atminkite, kad atominė klasė naudojama siekiant užtikrinti, kad bendrinami kintamieji free_index ir full_index būtų atnaujinami atomiškai. Mutex naudojamas apsaugoti kritinę sekciją, kurioje pasiekiamas bendras buferis. Funkcija „sleep_for“ naudojama prekių gamybai ir vartojimui imituoti.

ii) Pranešimų perdavimo metodas

Dabar pradėsime diskusiją apie procesų ryšį perduodant pranešimus. Taikant šį metodą, procesai bendrauja tarpusavyje nenaudodami jokios bendros atminties. Jei du procesai p1 ir p2 nori susisiekti vienas su kitu, jie elgiasi taip:

  • Užmegzkite ryšio ryšį (jei ryšys jau yra, nereikia jo užmegzti iš naujo).
  • Pradėkite keistis žinutėmis naudodami pagrindinius primityvus.
    Mums reikia bent dviejų primityvų:
    siųsti (pranešimas, paskirties vieta) arba siųsti (žinutė)
    gauti (pranešimas, priegloba) arba gauti (žinutė)

Pranešimo dydis gali būti fiksuoto dydžio arba kintamo dydžio. Jei jis yra fiksuoto dydžio, tai lengva OS dizaineriui, bet sudėtinga programuotojui, o jei yra kintamo dydžio, tai lengva programuotojui, bet sudėtinga OS dizaineriui. Standartinį pranešimą gali sudaryti dvi dalys: antraštė ir turinys.
The antraštės dalis naudojamas pranešimo tipui, paskirties ID, šaltinio ID, pranešimo ilgiui ir valdymo informacijai saugoti. Valdymo informacijoje yra informacijos, pvz., ką daryti, jei pritrūksta buferio vietos, eilės numeris, prioritetas. Paprastai žinutė siunčiama naudojant FIFO stilių.

Pranešimas perduodamas per komunikacijos nuorodą.
Tiesioginė ir netiesioginė komunikacijos nuoroda
Dabar pradėsime diskusiją apie komunikacijos ryšių diegimo būdus. Diegiant nuorodą, reikia atminti keletą klausimų, pavyzdžiui:

  1. Kaip nustatomos nuorodos?
  2. Ar nuoroda gali būti susieta su daugiau nei dviem procesais?
  3. Kiek sąsajų gali būti tarp kiekvienos bendravimo procesų poros?
  4. Kokia yra nuorodos talpa? Ar pranešimo dydis, kurį gali talpinti nuoroda, yra fiksuotas ar kintamas?
  5. Ar nuoroda yra vienakryptė ar dvikryptė?

Nuoroda turi tam tikrą talpą, kuri apibrėžia pranešimų, galinčių laikinai būti joje, skaičių, su kiekviena nuoroda susieta eilė, kuri gali būti nulinės, ribotos talpos arba neribotos talpos. Esant nulinei talpai, siuntėjas laukia, kol gavėjas praneš siuntėjui, kad pranešimą gavo. Ne nulinės talpos atvejais procesas nežino, ar pranešimas buvo gautas, ar ne po siuntimo operacijos. Tam siuntėjas turi aiškiai bendrauti su gavėju. Ryšio įgyvendinimas priklauso nuo situacijos, tai gali būti tiek tiesioginio ryšio, tiek netiesioginio ryšio ryšys.
Tiesioginės komunikacijos nuorodos diegiami, kai procesai komunikacijai naudoja konkretų proceso identifikatorių, tačiau sunku identifikuoti siuntėją iš anksto.
Pavyzdžiui, spausdinimo serveris.
Netiesioginis bendravimas atliekama per bendrą pašto dėžutę (prievadą), kurią sudaro pranešimų eilė. Siuntėjas saugo pranešimą pašto dėžutėje, o gavėjas juos pasiima.

Pranešimas perduodamas keičiantis žinutėmis.

Sinchroninis ir asinchroninis pranešimų perdavimas:
Užblokuotas procesas yra tas, kuris laukia kokio nors įvykio, pvz., resurso atsiradimo arba įvesties / išvesties operacijos pabaigos. IPC galimas tarp procesų tame pačiame kompiuteryje ir procesų, veikiančių kitame kompiuteryje, ty tinkle / paskirstytoje sistemoje. Abiem atvejais procesas gali būti blokuojamas arba neblokuojamas siunčiant pranešimą arba bandant gauti pranešimą, todėl pranešimas gali būti blokuojamas arba neblokuojamas. Svarstomas blokavimas sinchroninis ir blokuojantis siuntimas reiškia, kad siuntėjas bus užblokuotas, kol gavėjas gaus pranešimą. Panašiai, blokavimas gauti blokuoja imtuvą, kol gaunamas pranešimas. Atsižvelgiama į neblokavimą asinchroninis ir Neblokuojantis siuntimas reiškia, kad siuntėjas išsiunčia pranešimą ir tęsia. Panašiai, neblokuojantis priėmimas, gavėjas gauna galiojantį pranešimą arba nulinį. Po kruopščios analizės galime padaryti išvadą, kad siuntėjui yra natūraliau neblokuoti po pranešimo, nes gali prireikti siųsti žinutę į skirtingus procesus. Tačiau siuntėjas tikisi iš gavėjo patvirtinimo, jei siuntimas nepavyktų. Panašiai yra natūraliau, kad gavėjas blokuoja po priėmimo, nes informacija iš gauto pranešimo gali būti naudojama tolesniam vykdymui. Tuo pačiu metu, jei žinutės siuntimas ir toliau nepavyks, gavėjas turės laukti neribotą laiką. Todėl svarstome ir kitą pranešimo perdavimo galimybę. Iš esmės yra trys pageidaujami deriniai:

  • Blokuoti siuntimą ir blokuoti priėmimą
  • Neblokuojantis siuntimas ir neblokuojantis priėmimas
  • Neblokuojantis siuntimas ir blokuojantis priėmimas (dažniausiai naudojamas)

Tiesioginis pranešimų siuntimas , Procesas, kuriuo norima bendrauti, turi aiškiai nurodyti pranešimo gavėją arba siuntėją.
pvz. siųsti (p1, žinutė) reiškia siųsti žinutę į p1.
Panašiai, gauti (p2, pranešimas) reiškia gauti pranešimą iš p2.
Taikant šį ryšio būdą, ryšio ryšys užmezgamas automatiškai, kuris gali būti vienakryptis arba dvikryptis, tačiau viena nuoroda gali būti naudojama tarp vienos siuntėjo ir gavėjo poros, o viena siuntėjo ir gavėjo pora neturėtų turėti daugiau nei vienos poros nuorodos. Taip pat galima įgyvendinti simetriją ir asimetriją tarp siuntimo ir gavimo, t. y. arba abu procesai pavadins vienas kitą siųsdami ir priimdami pranešimus, arba tik siuntėjas įvardins gavėją, kad siųstų pranešimą, o gavėjui nereikia įvardinti siuntėjo. žinutės gavimas. Šio ryšio būdo problema ta, kad pasikeitus vieno proceso pavadinimui šis metodas neveiks.
Netiesioginio pranešimo perdavimo režimu , procesai laiškams siųsti ir gauti naudoja pašto dėžutes (taip pat vadinamas prievadais). Kiekviena pašto dėžutė turi unikalų ID ir procesai gali bendrauti tik tuo atveju, jei jie bendrina pašto dėžutę. Nuoroda sukurta tik tuo atveju, jei procesai turi bendrą pašto dėžutę ir viena nuoroda gali būti susieta su daugeliu procesų. Kiekviena procesų pora gali dalytis keliomis ryšio nuorodomis ir šios nuorodos gali būti vienakryptės arba dvikryptės. Tarkime, kad du procesai nori bendrauti per netiesioginį pranešimų perdavimą, reikalingos operacijos yra: sukurti pašto dėžutę, naudoti šią pašto dėžutę žinutėms siųsti ir gauti, tada sunaikinti pašto dėžutę. Naudojami standartiniai primityvai: siųsti (A, žinutė) o tai reiškia siųsti žinutę į pašto dėžutę A. Primityvus pranešimui gauti taip pat veikia taip pat pvz. gauta (A, žinutė) . Iškilo šio pašto dėžutės diegimo problema. Tarkime, kad yra daugiau nei du procesai, turintys tą pačią pašto dėžutę, ir tarkime, kad procesas p1 siunčia pranešimą į pašto dėžutę, kuris procesas bus gavėjas? Tai galima išspręsti nustatant, kad tik du procesai gali dalytis viena pašto dėžute, arba nustatant, kad tik vienam procesui būtų leista vykdyti gavimą tam tikru metu arba atsitiktinai pasirenkant bet kurį procesą ir pranešant siuntėjui apie gavėją. Pašto dėžutė gali būti privati ​​vienai siuntėjo / gavėjo porai, taip pat gali būti bendrinama kelioms siuntėjų / gavėjų poroms. Prievadas yra tokios pašto dėžutės, kuri gali turėti kelis siuntėjus ir vieną gavėją, įgyvendinimas. Jis naudojamas kliento/serverio programose (šiuo atveju serveris yra imtuvas). Prievadas priklauso priėmimo procesui ir jį sukuria OS imtuvo proceso prašymu ir gali būti sunaikintas to paties imtuvo procesoriaus prašymu, kai imtuvas pats išsijungia. Įtikinti, kad tik vienam procesui leidžiama vykdyti gavimą, galima naudoti abipusio išskyrimo koncepciją. Mutex pašto dėžutė sukuriamas, kurį bendrina n procesas. Siuntėjas neblokuoja ir siunčia pranešimą. Pirmasis procesas, kuris vykdo gavimą, pateks į kritinę sekciją, o visi kiti procesai bus blokuojami ir lauks.
Dabar aptarkime gamintojo ir vartotojo problemą, naudodamiesi žinutės perdavimo koncepcija. Gamintojas įdeda prekes (žinučių viduje) į pašto dėžutę ir vartotojas gali suvartoti prekę, kai pašto dėžutėje yra bent vienas pranešimas. Kodas pateiktas žemiau:
Gamintojo kodas

C




void> Producer(>void>){> > >int> item;> >Message m;> > >while>(1){> > >receive(Consumer, &m);> >item = produce();> >build_message(&m , item ) ;> >send(Consumer, &m);> >}> >}>

>

>

Vartotojo kodas

C




void> Consumer(>void>){> > >int> item;> >Message m;> > >while>(1){> > >receive(Producer, &m);> >item = extracted_item();> >send(Producer, &m);> >consume_item(item);> >}> >}>

>

>

IPC sistemų pavyzdžiai

  1. Posix: naudoja bendrosios atminties metodą.
  2. Mach : naudoja pranešimų perdavimą
  3. „Windows XP“: naudoja pranešimų perdavimą vietiniais procedūriniais skambučiais

Komunikacija kliento/serverio architektūroje:
Yra įvairių mechanizmų:

  • Vamzdis
  • Lizdas
  • Nuotoliniai procedūriniai skambučiai (RPC)

Pirmiau minėti trys metodai bus aptarti vėlesniuose straipsniuose, nes visi jie yra gana konceptualūs ir nusipelno atskirų straipsnių.
Nuorodos:

  1. Operacinės sistemos koncepcijos, kurias pateikė Galvin ir kt.
  2. Ariel J. Frank, Bar-Ilan universiteto paskaitų konspektas/ppt

Tarpprocesinis ryšys (IPC) yra mechanizmas, per kurį procesai arba gijos gali bendrauti ir keistis duomenimis vieni su kitais kompiuteryje arba tinkle. IPC yra svarbus šiuolaikinių operacinių sistemų aspektas, nes jis leidžia skirtingiems procesams veikti kartu ir dalytis ištekliais, todėl padidėja efektyvumas ir lankstumas.

IPC privalumai:

  1. Leidžia procesams bendrauti tarpusavyje ir dalytis ištekliais, todėl padidėja efektyvumas ir lankstumas.
  2. Palengvina kelių procesų koordinavimą, todėl bendras sistemos veikimas yra geresnis.
  3. Leidžia kurti paskirstytas sistemas, kurios gali apimti kelis kompiuterius ar tinklus.
  4. Gali būti naudojamas diegti įvairius sinchronizavimo ir ryšio protokolus, tokius kaip semaforai, vamzdžiai ir lizdai.

IPC trūkumai:

  1. Padidina sistemos sudėtingumą, todėl ją sunkiau kurti, įdiegti ir derinti.
  2. Gali įnešti saugumo spragų, nes procesai gali pasiekti arba modifikuoti kitiems procesams priklausančius duomenis.
  3. Norint užtikrinti, kad IPC operacijos nepablogintų bendro sistemos našumo, reikia atidžiai valdyti sistemos išteklius, pvz., atmintį ir procesoriaus laiką.
    Gali atsirasti duomenų neatitikimų, jei keli procesai bando pasiekti arba modifikuoti tuos pačius duomenis vienu metu.
  4. Apskritai IPC privalumai nusveria trūkumus, nes tai yra būtinas šiuolaikinių operacinių sistemų mechanizmas ir leidžia procesams dirbti kartu bei dalytis ištekliais lanksčiai ir efektyviai. Tačiau reikia atidžiai kurti ir įdiegti IPC sistemas, kad būtų išvengta galimų saugumo spragų ir našumo problemų.

Daugiau nuorodų:
http://nptel.ac.in/courses/106108101/pdf/Lecture_Notes/Mod%207_LN.pdf
https://www.youtube.com/watch?v=lcRqHwIn5Dk