Utangulizi wa usindikaji wa mawasiliano kwenye Linux. Badilisha data kati ya michakato kwa kutumia maeneo ya kumbukumbu yaliyoshirikiwa

Kupanga kwa Linux. SEHEMU YA 2.

Linux API - Utangulizi wa Mchakato wa Maingiliano

mwingiliano

Andrey Borovsky

Uwepo katika mifumo ya Unix ya rahisi na njia za ufanisi mwingiliano

kati ya michakato haikuwa na athari muhimu sana kwenye programu katika Unix

athari kuliko kuwakilisha vitu vya mfumo kama faili. Shukrani kwa

Msanidi wa Inter-Process Communication (IPC).

(na mtumiaji) anaweza kuvunja suluhisho la shida ngumu katika shughuli kadhaa rahisi, ambayo kila moja imekabidhiwa kwa programu ndogo tofauti.

Usindikaji mfululizo wa kazi moja kwa kadhaa programu rahisi inafanana sana na uzalishaji wa conveyor (kati ya maana nyingi za bomba la Kiingereza pia kuna "conveyor", lakini katika makala hii tutatumia neno "channel" iliyokubaliwa katika maandiko ya Kirusi ili kutafsiri neno bomba).

Njia mbadala ya njia ya bomba ni vifurushi vikubwa vya monolithic vyote kwa moja. Kutumia seti huduma rahisi ili kutatua tatizo moja tata, inahitaji ujuzi kidogo zaidi kwa upande wa mtumiaji, lakini kwa kurudi hutoa kubadilika ambayo haipatikani wakati wa kutumia "monsters" za monolithic. Seti za huduma zinazotumia itifaki za IPC wazi ni rahisi kupanua na kurekebisha. Kugawanya matatizo changamano katika majukumu madogo madogo pia husaidia kupunguza idadi ya makosa yanayofanywa na waandaaji programu (angalia utepe). Kando na haya yote, IPC ina faida nyingine muhimu. Programu zinazotumia IPC zinaweza "kuzungumza"

na kila mmoja karibu kwa ufanisi kama kwa mtumiaji, na kusababisha uwezo wa kufanya kazi ngumu otomatiki.

Nguvu ya Hati Lugha za Unix na Linux hutegemea sana uwezo wa IPC.

Katika makala hii tutajiwekea kikomo kwa kuzingatia IPC kwa kutumia aina mbalimbali za chaneli. Inachukuliwa kuwa wasomaji wa makala ni watumiaji wenye uzoefu Linux, na, kwa hali yoyote, unajua jinsi ya kuunda vituo kutoka kwa programu kadhaa kwa kutumia mstari wa amri. Kwa mtazamo wa mtayarishaji programu, utendakazi wa programu kwenye chaneli iliyopangwa kwa kutumia ishara ya “|” inaonekana rahisi sana. Pato la kawaida la programu moja linaelekezwa kwenye pembejeo ya kawaida ya programu nyingine, ambayo matokeo yake ya kawaida yanaweza pia kuelekezwa kwingine. Lakini vipi ikiwa unahitaji kutumia chaneli ndani ya programu yenyewe?

Sheria ya Brooks Frederick Brooks, mwandishi wa The Mythical Man-Month, alipendekeza (inayojulikana kama "Brooks' Law") kwamba idadi ya makosa katika mradi ni sawia na mraba ya idadi ya washiriki wa mradi, wakati kiasi kazi muhimu inahusiana na idadi ya washiriki kwa uhusiano wa mstari.

Ikiwa sheria ya Brooks ilikuwa kweli, basi katika hatua fulani maendeleo ya mradi, jaribio lolote la kuvutia watengenezaji wapya litasababisha kuongezeka kwa idadi ya makosa kama maporomoko ya theluji, na hitaji la kusahihisha linaweza kuchukua rasilimali zote za mradi. Kwa maneno mengine, kwa mujibu wa sheria ya Brooks, kwa miradi ya programu kuna kizingiti fulani cha utata, kinachozidi ambayo husababisha kushuka kwa kasi kwa ufanisi. Kuhusu mfano wazi maendeleo ya programu, basi, kutoka kwa mtazamo wa sheria ya Brooks, inapaswa kuwa haiwezekani kwa kanuni. Ili kuelewa ni wapi F. Brooks alikosea, mtu anapaswa kuzingatia maeneo ya kuanzia ya hoja yake. Sheria ya Brooks inategemea mawazo mawili: (a) makosa mara nyingi hutokea kwenye makutano ya vipengele vya mradi vinavyofanywa na watengenezaji tofauti (ivyo hivyo, "seams" zaidi kama hizo, makosa zaidi);

(b) muundo wa mwingiliano wa wasanidi programu ni grafu kamili (yaani, kila msanidi programu hutangamana na washiriki wengine wote wa mradi), idadi ya kingo zake ambayo ni sawia na mraba wa idadi ya vipeo. Hakuna taarifa moja au nyingine, kwa ujumla, sio sahihi. Hasa, ikiwa suluhisho la tatizo tata linasambazwa kati ya huduma kadhaa ndogo, washiriki wote wa mradi hawana haja ya kuingiliana moja kwa moja. Kila timu ya maendeleo lazima ifuate itifaki maalum tu ya kuwasiliana kati ya programu, ili katika kesi hii idadi ya makosa ifuate uhusiano wa mstari, badala ya quadratic.

Mabomba Yasiyo na Jina Matumizi ya kawaida ya mirija ya ndani ya programu ni wakati programu inapoendesha programu nyingine na kusoma data ambayo inaandika kwa mkondo wake wa pato wa kawaida. Kwa hila hii, msanidi programu anaweza kutumia utendaji wa programu nyingine katika programu yake bila kuingilia maelezo ya ndani ya uendeshaji wake. Ili kutatua tatizo hili tutatumia kazi za popen(3) na pclose(3). Hapo awali, chaguo za kukokotoa hizi ni sawa na vitendakazi vya fopen(3) na fclose(3). Chaguo za kukokotoa za popen() huendesha programu ya nje na hurejesha kwa programu ya kupiga simu kielekezi kwa muundo wa FILE unaohusishwa na mtiririko wa kawaida wa ingizo au mtiririko wa kawaida wa utoaji wa mchakato unaoendeshwa. Kigezo cha kwanza cha kazi ya popen() ni kamba iliyo na amri inayoendesha programu ya nje. Kigezo cha pili huamua ni mtiririko upi wa kawaida (toleo au ingizo) utarejeshwa. Hoja ya "w" inalingana na mtiririko wa ingizo wa programu inayozinduliwa, ambapo programu inayoita popen() huandika data kwenye mtiririko. Hoja ya "r" inalingana na mkondo wa pato. Kitendaji cha pclose() hutoka kwenye programu ya nje na kufunga kituo. Ili kuonyesha jinsi ya kutumia kazi za popen()/pclose(), tutaandika programu ndogo inayoitwa makelog (maandishi kamili ya programu yanaweza kupatikana kwenye diski kwenye faili ya makelog.c) Programu ya makelog inatekeleza amri ya shell iliyopitishwa. kwake kama kigezo na kuandika matokeo ya amri hiyo, wakati huo huo kwa terminal ya kawaida na faili ya log.txt (ina vitendaji sawa. amri ya kawaida tee). Kwa mfano, ikiwa unakusanya programu:



gcc makelog.c -o makelog na kisha amri makelog "ls -al" itachapisha matokeo ya ls -al shell amri kwenye skrini ya mwisho, na faili ya log.txt iliyo na data sawa itaundwa katika kufanya kazi kwa programu ya makelog. saraka. Alama za nukuu karibu na amri ya ganda zinahitajika ili kuhakikisha kuwa makelog inapokea safu ya amri kama kigezo cha mstari wa amri moja.

Msomaji labda tayari amekisia kuwa kivutio cha programu ya makelog ni matumizi ya popen() kazi. Wacha tuangalie kipande cha nambari ya chanzo cha programu:

f = popen(argv, "r");

Operesheni hii ni sawa na kufungua faili ya kawaida kwa kusoma.

Tofauti f ina Aina ya FILE*, lakini ndani parameta argv Kazi ya popen() haijapitishwa jina la faili, lakini amri ya kuendesha programu au amri ya shell, kwa mfano, "ls -al". Ikiwa popen() simu ilifanikiwa, tunaweza kusoma matokeo ya amri inayoendesha kwa kutumia kazi ya kawaida ya fread(3):

fread(buf, 1, BUF_SIZE, f) Upekee wa chaguo za kukokotoa popen() ni kwamba chaguo hili la kukokotoa halirudishi NULL, hata kama amri iliyopitishwa kwake si sahihi.

Njia rahisi ya kugundua kosa katika hali hii ni kujaribu kusoma data kutoka kwa mkondo wa pato. Ikiwa hakuna data kwenye mkondo wa pato (fread() inarudisha 0), basi hitilafu imetokea. Ili kutoa data iliyosomwa na fread() kwa terminal, tunatumia kazi ya write(), kubainisha mpini kwa mkondo wa pato wa kawaida:

andika (1, buf, len);

Sambamba, data sawa imeandikwa kwa faili kwenye diski. Baada ya kusoma data, chaneli wazi lazima ifungwe:

Kumbuka kwamba pclose() itarejesha udhibiti kwa mazungumzo ya kupiga simu tu baada ya programu kuanzishwa kwa kutumia popen() kukamilisha kazi yake.

Kwa kumalizia, wacha tuangalie kipengele kimoja zaidi cha kazi ya popen(). Ili kutekeleza amri iliyopitishwa kwake, popen() kwanza huzindua mfano wake wa ganda, ambayo ni nzuri kwa upande mmoja, lakini sio nzuri sana kwa upande mwingine. Hii ni nzuri kwa sababu kupiga simu popen() hufanya shughuli za ndani kiotomatiki (kama vile kuchakata muundo wa jina la faili), kwa kutumia anuwai za mazingira kama PATH na HOME, n.k. Kando ya njia ya popen() ni sehemu ya ziada ya kuanza mchakato wa ganda, ambayo sio lazima wakati ganda lenyewe halihitajiki kutekeleza programu ya nje.

Chaguo za kukokotoa za popen() hutumia mirija kuwasiliana na programu ya nje. Tunaweza kutumia chaneli moja kwa moja katika programu zetu. Aina ya kawaida ya mabomba ni mabomba yasiyojulikana, yaliyoundwa na kazi ya bomba (2). Katika kiwango cha interface cha programu, chaneli kama hiyo inawakilishwa na maelezo mawili ya faili, moja ambayo hutumiwa kusoma data, na nyingine kwa maandishi. Vituo havitumii ufikiaji wa nasibu, kumaanisha kwamba data inaweza kusomwa tu kwa mpangilio uleule ambao iliandikwa.

Mabomba yasiyo na jina hutumika kimsingi kwa kushirikiana na kitendakazi cha uma(2) na hutumika kubadilishana data kati ya michakato ya mzazi na mtoto. Ili kuandaa ubadilishanaji wa data kama hiyo, kwanza, kwa kutumia bomba () kazi, kituo kinaundwa. Kitendaji cha bomba () kinapitishwa kwa parameta moja - safu chapa int, yenye vipengele viwili. Katika kipengele cha kwanza cha safu, kazi inarudi maelezo ya faili yaliyotumiwa kusoma data kutoka kwa kituo (matokeo ya kituo), na kwa pili - maelezo ya kuandika (pembejeo). Kisha, kwa kutumia uma () kazi, mchakato ni "uma". Mchakato wa mtoto hurithi vipini vyote viwili vilivyofunguliwa na pipe() kutoka kwa mchakato wa mzazi, lakini, kama mchakato wa mzazi, lazima itumie moja tu ya vipini.

Mwelekeo wa uhamishaji data kati ya michakato ya mzazi na mtoto huamuliwa na mpini gani utatumiwa na mchakato wa mzazi na ambao mtoto. Tutaonyesha yaliyo hapo juu mfano rahisi pipes.c programu, inayotumia vitendaji vya bomba() na fork().

#jumuisha #jumuisha #jumuisha int main (int argc, char * argv) int pipedes;

char *str = "Kamba iliyopitishwa kupitia bomba\n";

andika(mabomba, (batili *) str, strlen(str) + 1);

huku ((len = soma(mabomba, buf, 1024)) != 0) andika(2, buf, len);

Maelezo ya bomba zote mbili huhifadhiwa kwenye utofauti wa bomba. Baada ya kupiga simu uma (), mchakato umegawanywa na mchakato wa mzazi (ule ambao uma () ulirudisha thamani isiyo ya sifuri sawa na PID ya mchakato wa mtoto) hufunga kipini cha kusoma na kuandika data kwa bomba kwa kutumia maandishi. kushughulikia (mabomba). Mchakato wa mtoto (ambapo fork() ulirudishwa 0) hufunga kipini cha uandishi na kisha kusoma data kutoka kwa bomba kwa kutumia kipini cha kusoma (bomba). Madhumuni ya vifafanuzi ni rahisi kukumbuka kwa kulinganisha na kifupi cha I/O (kielezi cha kwanza ni cha kusoma (ingizo), pili ni kwa maandishi (pato)). Kiwango cha POSIX kinahitaji kwamba kila mchakato unaopokea mishikio yote miwili ya chaneli ufunge kishikio ambacho hakihitaji kabla ya kuhamia kwenye mpini mwingine, na ingawa hitaji hili linaweza kupuuzwa kwenye Linux, ni bora kushikamana na sheria kali.

Katika mfano wetu, hatuna haja ya kuwa na wasiwasi kuhusu kusawazisha uhamishaji wa data kwa sababu kernel ya mfumo itatufanyia kazi ngumu. Lakini katika maisha pia hakuna kesi ndogo sana. Kwa mfano, hakuna kitu kinachotuzuia kuunda michakato mingi ya watoto kwa kutumia simu nyingi za fork(). Taratibu hizi zote zinaweza kutumia bomba sawa, mradi kila mchakato unatumia moja tu ya vipini vya bomba, kulingana na madhumuni yake.

Katika hali hii, tutalazimika kusawazisha kwa uwazi uhamishaji wa data.

Jinsi bomba huhamisha data Ili kuhamisha data kwa kutumia mabomba, maeneo maalum ya kumbukumbu (yaliyoundwa na kernel ya mfumo) hutumiwa, inayoitwa buffers ya bomba.

Moja ya vipengele muhimu buffer za chaneli ni kwamba hata kama maandishi ya awali hayakujaza kabisa bafa, kuandika upya data kwa bafa kunawezekana tu baada ya data iliyoandikwa hapo awali kusomwa. Hii inamaanisha kuwa ikiwa michakato tofauti ya kuandika data kwa data ya uhamishaji wa chaneli sawa katika vizuizi ambavyo saizi zake hazizidi saizi ya vihifadhi, data kutoka kwa vizuizi vilivyoandikwa na michakato tofauti haitachanganywa. Kutumia kipengele hiki cha chaneli hurahisisha sana ulandanishi wa utumaji data. Unaweza kujua saizi ya bafa kwa kupiga kazi fpathconf(pipedes, _PC_PIPE_BUF) ambapo pipedes ndio kielezi cha bomba. Kwenye jukwaa la IA32, saizi ya bafa ya kituo kimoja ni kilobaiti 4. Kuanzia toleo la kernel 2.6.11, kila Kituo cha Linux inaweza kutumia hadi buffer 16, ambayo huboresha sana utendakazi wa kituo.

Mara tu tunapofahamu mabomba ambayo hayajatajwa, tunaweza kutekeleza analogi ya popen() kazi wenyewe bila "gharama ya ziada" (hiyo ni, bila kuendesha mchakato wa kufunika). Hebu tuandike programu ndogo inayoendesha matumizi ya netstat, husoma matokeo ya matumizi haya na kuyachapisha kwenye skrini. Ikiwa tungetumia chaguo za kukokotoa za popen() kwa madhumuni haya, tungefikia mkondo wa pato wa netstat kwa kupiga simu popen("netstat", "r");

Njia hii ni rahisi, lakini haifai. Tutaandika programu nyingine (faili ya printns.c). Muundo wa programu hii ni sawa na katika mfano uliopita, tu sasa mchakato wa mzazi unasoma data kwa kutumia bomba kwa uwazi.

Jambo la kufurahisha zaidi hufanyika katika mchakato wa mtoto, ambapo mlolongo wa kazi unatekelezwa:

dup2(mabomba, 1);

execve("/bin/netstat", NULL, NULL);

Kwa chaguo la kukokotoa la dup2(2), tunaelekeza upya pato la kawaida la mchakato wa mtoto (kielezi cha kawaida cha pato ni 1) kwenye bomba kwa kutumia kishikio cha pipdes, ambacho kimefunguliwa kwa maandishi. Ifuatayo, tunatumia kazi ya execve(2) kuchukua nafasi ya picha ya mchakato wa mtoto na mchakato wa netstat (kumbuka kuwa kwa kuwa hatuna ganda na yake. kutofautiana kwa mazingira PATH, njia ya faili inayoweza kutekelezwa ya netstat lazima ibainishwe kikamilifu).

Mabomba Yanayoitwa Ingawa mfano hapo juu unatumia bomba zisizo na jina tu kuhamisha data kati ya michakato inayohusiana, inawezekana kuzitumia kuhamisha data kati ya michakato tofauti kabisa. Ili kufanya hivyo, unahitaji kupanga uhamisho wa maelezo ya kituo kati ya michakato isiyohusiana, kama ilivyoelezwa, kwa mfano, katika. Hata hivyo, kupitisha vipini kwa mchakato wa mtu wa tatu ni zaidi ya hila (au "hack"), na hatutakaa juu yake. Ili kuhamisha data kati ya michakato isiyohusiana, tutatumia utaratibu wa mabomba yenye jina, ambayo inaruhusu kila mchakato kupata maelezo yake ya "kisheria" ya bomba. Usambazaji wa data katika chaneli hizi (kama, kwa kweli, katika njia zisizo na majina) unategemea kanuni ya FIFO (iliyoandikwa kwanza, kusoma kwanza), kwa hivyo katika fasihi ya Kiingereza wakati mwingine unaweza kupata majina mabomba ya FIFO au FIFOs tu. Mabomba yaliyotajwa yanatofautiana na mabomba yasiyo na jina kwa uwepo wa jina (ajabu, sivyo?), yaani, kitambulisho cha kituo kinachoweza kuonekana kwa michakato yote katika mfumo. Ili kutambua bomba iliyoitwa, bomba maalum la aina ya faili huundwa. Huyu ni mshiriki mwingine wa familia ya Unix ya faili pepe ambazo hazikusudiwa kuhifadhi data (saizi ya faili ya bomba huwa kila wakati sawa na sifuri) Faili za bomba zilizopewa jina ni vitu vya VFS, kama vile za kawaida. Faili za Linux, na sheria sawa za udhibiti wa ufikiaji zinatumika kwao. Unaweza kutumia mkfifo(3) kazi ya kuunda faili za bomba zilizopewa jina. Kigezo cha kwanza cha kazi hii ni kamba iliyo na jina la faili ya kituo, parameter ya pili ni mask ya haki za upatikanaji wa faili. Kazi ya mkfifo() huunda bomba na faili ya aina inayofaa. Kama faili maalum kituo tayari kipo, mkfifo() inarudisha -1 (errno imewekwa kuwa EEXIST). Mara tu faili ya kituo inapoundwa, michakato inayohusika katika mawasiliano lazima ifungue faili kwa ajili ya kuandika au kusoma. Kumbuka kwamba baada ya faili ya kituo kufungwa, faili (na kituo chake sambamba) inaendelea kuwepo. Ili kufunga kituo chenyewe, unahitaji kufuta faili yake, kwa mfano kutumia simu zinazofuatana ili kutenganisha(2).

Wacha tuangalie jinsi bomba inayoitwa inavyofanya kazi kwa kutumia mfano wa mfumo rahisi wa seva ya mteja. Programu ya seva huunda kituo na kupitisha maandishi yaliyoingizwa na mtumiaji kutoka kwa kibodi ndani yake. Programu ya mteja inasoma maandishi na kuyatoa kwa terminal. Programu katika mfano huu zinaweza kuchukuliwa kama toleo lililorahisishwa la mfumo wa ujumbe wa papo hapo kati ya watumiaji wa OS yenye watumiaji wengi. Maandishi asilia Programu ya seva imehifadhiwa kwenye faili typeserver.c. Kupigia simu mkfifo() kazi huunda faili ya kitambulisho cha kituo kwenye saraka ya kufanya kazi ya programu:

mkfifo(FIFO_NAME, 0600);

ambapo FIFO_NAME ni jumla inayobainisha jina la faili ya kituo (kwa upande wetu fifofile").

Kama kinyago cha ufikiaji, tunatumia thamani ya octal 0600, ambayo inaruhusu mchakato ulio na maelezo sawa ya mtumiaji kusoma na kuandika (tunaweza kutumia barakoa ya 0666, lakini ikiwezekana, tutaepuka kutaja Nambari ya Mnyama, hata octal, katika programu yetu). Kwa ufupi, hatuangalii thamani iliyorejeshwa na mkfifo() kwa makosa. Kama matokeo ya kupiga simu mkfifo() na vigezo vilivyotolewa inapaswa kuonekana kwenye saraka ya kazi ya programu faili maalum faili. Kidhibiti faili cha KDE kinaonyesha faili za kituo na ikoni nzuri ya bomba la maji lililo wazi kidogo. Ifuatayo, katika programu ya seva, tunafungua faili iliyoundwa kwa kuandika:

f = fopen(FIFO_NAME, "w");

Kusoma pembejeo la mtumiaji hufanywa kwa kutumia getchar() na kwa kutumia fputc() kazi data hupitishwa kwenye bomba. Seva huisha mtumiaji anapoingiza herufi "q". Msimbo wa chanzo wa programu ya mteja unaweza kupatikana katika faili typeclient.c. Mteja anafungua fifofile kwa kusoma kama faili ya kawaida:

f = fopen(FIFO_NAME, "r");

Herufi zilizotumwa juu ya chaneli husomwa kwa kutumia fgetc() kazi na pato kwa skrini ya terminal kwa kutumia putchar(). Kila wakati mtumiaji wa seva anapokea pembejeo, kazi ya fflush() inayoitwa na seva (ona

typeserver.c file) hulazimisha buffer za chaneli kusafishwa, na kusababisha mteja kusoma herufi zote zinazotumwa. Kupokea herufi "q" hukatisha mteja.

Kusanya programu typeserver.c na typeclient.c katika saraka sawa.

Anzisha seva kwanza, kisha mteja kwenye windows terminal tofauti. Andika maandishi kwenye dirisha la seva. Baada ya kila kibonye, ​​mteja anapaswa kuonyesha kamba iliyochapishwa kwenye seva.

Unaweza pia kuunda faili ya FIFO kwa kutumia kazi ya mknod(2), ambayo imeundwa kuunda aina mbalimbali za faili (FIFO, soketi, faili za kifaa, na faili za data za kawaida). Kwa upande wetu, badala ya mkfifo(fname, 0600);

mtu anaweza kuandika mknod(fname, S_IFFO, 0);

Moja ya nguvu za Unix/Linux IPC ni uwezo wa kupanga mwingiliano kati ya programu ambazo hazijui chochote kuhusu kila mmoja, lakini pia hutumia. mifumo tofauti pembejeo/pato. Wacha tulinganishe programu yetu ya typeclient na ls amri. Inaweza kuonekana kuwa hakuna kitu sawa kati yao - typeclient inapokea data kwa kutumia bomba iliyopewa jina, na ls hutoa yaliyomo kwenye saraka kwa mkondo wa pato la kawaida. Walakini, tunaweza kuhamisha data kutoka kwa ls hadi kwa typeclient kwa amri chache tu za bash! Kwenye saraka ya programu ya typeclient, toa amri:

mknod fifofile p Amri hii itaunda faili ya chaneli ya fifofile kama vile programu ya typeserver ingefanya. Endesha programu ya typeclient kisha kwenye kidirisha kingine toa amri kama ls -al > /path/fifofile ambapo /path/fifofile ndio njia ya faili ya FIFO. Kama matokeo, programu ya typeclient itachapisha yaliyomo kwenye saraka inayolingana. Jambo kuu ni kwamba mkondo wa data hauna tabia ya "q", ambayo inamaliza kazi yake.

Njia ni njia rahisi na rahisi ya kusambaza data, ambayo, hata hivyo, haifai katika hali zote. Kwa mfano, kutumia chaneli ni ngumu sana kupanga ubadilishanaji wa ujumbe wa asynchronous kati ya michakato. Katika makala inayofuata tutaangalia vipengele vingine vya IPC Unix/Linux, foleni za ujumbe na semaphores.

1. D. P. Bovet, M. Cesati, Kuelewa Linux Kernel, Toleo la 3, O'Reilly, 2. W. R. Stevens, S. A. Rago, Utayarishaji wa Kina katika Mazingira ya UNIX®: Toleo la Pili, Addison Wesley Professional, 3. Stevens W ., UNIX: Mwingiliano wa michakato - St. Petersburg: Peter,



Kazi zinazofanana:

"Wizara ya Elimu na Sayansi ya Shirikisho la Urusi Tahadhari! Faili ina programu ZOTE za sekta za uchumi wa taifa! PROGRAM - MINIMUM mtihani wa mgombea katika maalum 08.00.05 - Uchumi na usimamizi wa uchumi wa taifa (uchumi, shirika na usimamizi wa makampuni ya biashara, viwanda, complexes katika tata ya kilimo na kilimo) katika sayansi ya kiuchumi Programu ya chini ina kurasa 24 2007 2 Utangulizi Msingi wa programu hii ulikuwa masharti muhimu ya taaluma zifuatazo:..."

“IMETHIBITISHWA kwa agizo la mkurugenzi wa Chuo cha OGBPOU Kostroma Polytechnic Na. Masharti ya jumla 1.1. Utaratibu huu wa kuwafukuza, kuwarejesha na kuwahamisha wanafunzi wa taasisi ya elimu ya kitaalamu ya kibajeti ya serikali ya mkoa ya Kostroma Polytechnic College (hapa inajulikana kama..."

"Mkataba ulioainishwa ni wa umma kwa misingi ya Sanaa. 633 ya Kanuni ya Kiraia ya Ukraine na inalazimisha Biashara kutoa huduma ambazo ni mada ya makubaliano haya kwa kila mtu anayewasiliana nayo ikiwa ana fursa ya kumpa mtumiaji huduma zinazofaa. MAKUBALIANO ya utoaji wa huduma (kama ilivyorekebishwa mnamo Januari 22, 2013) Sevastopol _ 201 PE Sevtelecomservice, iliyowakilishwa na mkurugenzi Evgeniy Aleksandrovich Prividentsev, kaimu kwa msingi wa Mkataba, ambao unajulikana baadaye kama..."

"Ripoti ya umma kwa mwaka wa masomo wa 2011-2012 wa taasisi ya elimu ya shule ya mapema ya manispaa ya jiji la Kurgan Kindergarten No. 79 Rucheyok 1. Tabia za jumla Jina kamili la taasisi ya elimu: taasisi ya shule ya mapema ya bajeti ya manispaa. taasisi ya elimu mji wa Kurgan Shule ya chekechea Nambari 79 Mtiririko. Jina rasmi la kifupi: MBDOU Chekechea Na. 79. a) Tarehe ya kuundwa kwa taasisi ya elimu: Juni 1964. Mwanzilishi wa taasisi ya elimu: manispaa ya jiji la Kurgan inayowakilishwa na...”

“SHIRIKA LA ELIMU LA SHIRIKISHO la Chuo Kikuu cha Utalii na Tawi la Biashara la Mapumziko la Jimbo la Sochi huko Anapa LIMETHIBITISHWA na Mkurugenzi wa AF SGUT na KD I.I. Ashkinadze Ubunifu katika huduma ya kijamii na kitamaduni na programu ya kazi ya utalii ya taaluma (OZFO) Iliyopewa idara: Huduma ya kijamii na kitamaduni na utalii Mtaala: 100103 Umaalumu: Huduma ya kijamii na kitamaduni na utalii Masaa 120 kulingana na mtaala wa kufanya kazi: Masaa kulingana na Kiwango cha Elimu cha Jimbo (kutoka RUP ): Saa 120 kulingana na mpango wa kazi: Masaa takriban...."

“Luty 2013 TUNZA SIMULIZI YAKO YA MAFANIKIO na Mary Kay Mafanikio yako yatakuwa yapi inategemea wewe tu. Mary Kay atakuonyesha njia ya uzuri! Kutana na Mpango mpya wa Kivutio wa Biashara na Maendeleo wa Newbie! Ofa ya manufaa Pekee kwa Washauri wa Nyota wa robo ya II ya mwaka wa Semina 2012-2013! Kuanzia Februari 1 hadi Machi 31, 2013, kwa Washauri wote wa Star wa robo ya II ya mwaka wa Semina (Novemba 2012 - Januari 2013), Kampuni inatoa fursa ya kipekee ya kununua...

"Wizara ya Elimu na Sayansi ya Shirikisho la Urusi Taasisi ya Kielimu ya Bajeti ya Jimbo la Shirikisho la Elimu ya Juu ya Kitaalamu Chuo Kikuu cha Ufundishaji cha Jimbo la Krasnoyarsk kilichopewa jina lake. V.P. Astafieva Kitivo cha Biolojia, Jiografia na Kemia Idara ya Kemia MISINGI YA KEMISTARI YA JUU M.2 TATA YA ELIMU NA MBINU YA NIDHAMU Mwelekeo wa mafunzo: 050100.68 Elimu ya Ualimu Mpango wa Mwalimu Kemikali Elimu Krasnoyarsk 20111 Programu ya kufanya kazi iliyoandaliwa na Assoc. Idara ya Kemia, Ph.D. Beresnev V.A., Ph.D. Kuznetsova A.S. Mpango wa kazi ulijadiliwa saa ... "

“WIZARA YA KILIMO YA SHIRIKISHO LA URUSI Taasisi ya Kielimu ya Bajeti ya Serikali ya Shirikisho ya Elimu ya Taaluma ya Juu ya KUBAN STATE AGRICULTURAL UNIVERSITY WORK PROGRAM PROGRAMU YA KAZI YA CHUO KIKUU KIKUU CHA Nidhamu GSE. B.04 Saikolojia ya Uhandisi kwa taaluma 190601.65 Kitivo cha sekta ya magari na magari: mechanization Idara inayoongoza: Ualimu na saikolojia Aina ya kazi ya kitaaluma Elimu ya muda kamili Jumla ya saa Kozi, Mihadhara ya muhula mwaka wa 3, muhula wa 16 wa 5...”

“IMETHIBITISHWA na Mkurugenzi wa IMCES SB RAS, Daktari wa Sayansi ya Fizikia na Hisabati. _ V.A. Krutikov _ 2012 RIPOTI juu ya matokeo ya utafiti na matumizi ya fedha zilizopokelewa kusaidia kituo cha kisayansi cha Tayozhny cha Taasisi ya Ufuatiliaji wa Mifumo ya Hali ya Hewa na Ikolojia ya SB RAS mnamo 2012. Kituo cha kiikolojia cha "Taiga" cha IMCES SB RAS, iliyoundwa mnamo 2004, iko katika n. Nibega, wilaya ya Verkhneketsky, mkoa wa Tomsk, kwenye eneo la Priketye - moja ya maeneo yenye misitu ya sehemu ya mashariki ... "

"Noti ya ufafanuzi. Programu ya kazi ilitengenezwa kwa misingi ya: Mtaala wa Msingi wa Shirikisho (Amri ya Wizara ya Ulinzi ya Shirikisho la Urusi tarehe 9 Machi 2004) No. 1312; Agizo la Wizara ya Elimu ya Shirikisho la Urusi la tarehe 03/05/2004 No. 1089 (kama ilivyorekebishwa tarehe 10/19/2009) Kwa idhini ya sehemu ya shirikisho ya viwango vya elimu vya serikali vya msingi vya jumla, vya msingi na sekondari (kamili) elimu ya jumla; Agizo la Wizara ya Ulinzi ya Jamhuri ya Belarusi la tarehe 19 Agosti 2013 No. 1384 Juu ya mipango ya elimu iliyopendekezwa na mitaala ya sampuli ya taasisi za elimu za Jamhuri ya Belarusi mnamo...”

". Taasisi ya elimu ya bajeti ya manispaa shule ya sekondari Nambari 1 Imeidhinishwa. Imepitishwa na baraza la walimu. Inazingatiwa na MS (amri Na. 34 ya 08/30/2013) (itifaki Na. 11 ya 08/30/2013) walimu wa Mkurugenzi wa mzunguko wa kibinadamu (itifaki Na. 1 ya 08/29/2013) _ G.P. Khlustova WORK PROGRAM kwa Kiingereza, daraja la 10 Mwalimu: Strokova Nina Stepanovna Kimovsk 1 MAELEZO Mpango wa kazi unatungwa kwa misingi ya kipengele cha Shirikisho. kiwango cha serikali mkuu…”

“AGIZO LA SERIKALI YA MKOA WA PENZA la tarehe 19 Desemba, 2013 No. 972-ppP Penza Kuhusu marekebisho ya mpango wa serikali Maendeleo ya eneo la viwanda vya kilimo la Penza kwa 2014 - 2020, iliyoidhinishwa na Amri ya Serikali ya Penza. Mkoa wa tarehe 18 Septemba 2013 No. 691-ppP Ili kuleta kitendo cha kisheria cha kawaida kwa mujibu wa sheria ya sasa, kwa kuongozwa na Sheria ya Mkoa wa Penza ya tarehe 22 Desemba 2005 No. 906-ZPO Kuhusu Serikali ya Mkoa wa Penza ( na..."

"uundaji katika akili ya msomaji wa mitazamo ya uzuri (thamani ya kihisia) na hermeneutical (dhana ya kitamathali, kisemantiki) ili kuelewa kiini cha somo linalosomwa; 2) kazi za maendeleo: maendeleo ya hisia ya kujieleza kisanii, ladha ya fasihi; maendeleo ya uwezo wa mawasiliano; maendeleo ya hotuba; 3) kazi za kielimu: kukuza utamaduni wa mtazamo wa ubunifu wa kazi ya fasihi; kukuza mtazamo wa uzuri kuelekea kitabu kama chanzo cha hali ya kiroho, kutafakari...”

“KIAMBATISHO 2 SHIRIKISHO LA WAKALA WA UVUVI Taasisi ya Kielimu ya Bajeti ya Serikali ya Shirikisho la Elimu ya Taaluma ya Juu Chuo Kikuu cha Ufundi cha Jimbo la Kaliningrad (FSBEI HPE KSTU) IMETHIBITISHWA na Makamu Mkuu wa Sayansi A.V. Ivanov kuanzia 2012. PROGRAMU YA MTIHANI WA KUINGIA kwa shule ya kuhitimu 0510 maalum ya kisayansi. – Uwezekano wa nadharia na takwimu za hisabati Kaliningrad 2012 16 Programu ya mtihani wa kuingia iliandaliwa na: Daktari wa Sayansi ya Ufundi, Profesa V.A...."

“Serikali 122 ya Shirikisho la Urusi Nambari ya Usajili ya Chuo Kikuu cha Jimbo la St. miaka St. Petersburg Maombi ya kitaalam mafunzo Maombi haya kwa kiwango cha elimu ya Jimbo la St. Petersburg..."

"1. UPEO WA MAOMBI 1.1 Programu ya mafunzo ya hali ya juu Usimamizi wa shughuli za ubunifu katika muundo wa manispaa unakusudiwa wafanyikazi wa manispaa, wafanyikazi. taasisi za manispaa Mkoa wa Krasnodar. 1.2.Upeo wa maombi na wanafunzi wa ujuzi wa kitaaluma uliopatikana ni shughuli za wafanyakazi katika kutekeleza kazi za manispaa na utoaji wa huduma za manispaa. 2. SIFA ZA MAANDALIZI CHINI YA MPANGO 2.1. Muda wa kawaida wa kusimamia programu ni saa 72...."

“OFISI YA KIMATAIFA YA AFISI YA KAZI Kikao cha 322, Geneva, Oktoba 30-Novemba 13, 2014 GB.322 Agenda na Mpango Ajenda ya Sehemu ya Masuala ya Kitaasisi ya INS Kupitishwa kwa muhtasari wa kikao cha 321 cha Baraza Linaloongoza. 1. Agenda Mkutano wa kimataifa kazi. 2. Maandalizi ya tathmini ya athari za Azimio la ILO kuhusu Haki ya Kijamii kwa Utandawazi wa Haki kwa Kikao cha 105 cha Mkutano wa Kimataifa wa Kazi (2016). Maswali yanayoibuka ... "

"Shrayberg Ya.L., Goncharov M.V., Shlykova O.V. Rasilimali za mtandao na huduma za maktaba: kitabu cha maandishi. posho. - M.: B.I., 2000. - 140 p. Shrader Yu.A. Mbinu ya kiisimu kwa nadharia mifumo ya habari// Kisayansi Taarifa za kiufundi, 1962. - Nambari 9. Schrader Yu.A. Thesauruses katika sayansi ya kompyuta na semantiki za kinadharia // NTI. Seva 2. - 1971. - Nambari 3. Eco U. Kutoka kwenye mtandao hadi Gutenberg: maandishi na hypertext. - Njia ya ufikiaji: http:// www.artinfo.ru/text Picha za kielektroniki na sanaa za kuona: Nyenzo kati ya ... "

"Jiografia. Kiwango cha msingi cha. DARASA LA 10-11. (SAA 68) Kitabu cha kiada: A.P. Kuznetsov, E.V. Kim Jiografia. Kiwango cha msingi cha. 10-11 darasa M.: Bustard, 2012. Mpango: Mpango wa elimu ya msingi katika jiografia. 5-9 darasa. Waandishi A.I. Alekseev, O.A. Klimanova, V.V. Klimanov, V.A. Nizovtsev, E.V. Kim. (chanzo Maabara ya Methodological ya jiografia MIOO) Maelezo ya ufafanuzi: Jiografia ya Kozi. Kiwango cha msingi cha. kulingana na programu za kozi za Jumla za Jiografia na Mafunzo ya Kikanda (O.A. Klimanova,...”

“Programu ya MAONYESHO Yaliyomo Hotuba ya ufunguzi ya Mkurugenzi Mkuu wa Metro Cash & Carry Russia WWW.METRO-EXPO.RU YALIYOMO Hotuba ya ufunguzi ya Rais wa kundi la makampuni ya Unilever nchini Urusi, Ukraine na Belarus. 5 Mpango wa maonyesho Orodha ya washiriki Stand M1. La carte restaurant Stand M2. Stendi ya Caf M3. Nunua karibu na nyumba Beans Stand M4. Ofisi ya Dunia Stand M5. Nyama na kuku Stand M6. Samaki na dagaa Stand M7. Jibini na vyakula vitamu Simama M8. Matunda na mboga Stand M9. Utoaji Stendi M10. Udhibiti wa ubora ... "

Jinsi ya Kutumia Foleni za Ujumbe, Semaphores, na Kumbukumbu Inayoshirikiwa Kuunganisha Programu

Michakato inayosimamiwa na kernel ya UNIX huendeshwa kwa uhuru, na kusababisha mfumo thabiti zaidi. Hata hivyo, kila msanidi hatimaye anajikuta katika hali ambapo kundi moja la michakato lazima liwasiliane na kundi lingine, kwa mfano, kubadilishana data au kupitisha amri. Njia hii ya kutuma ujumbe inaitwa Mawasiliano kati ya Mchakato (IPC) Uainishaji wa Mfumo wa V wa UNIX (SysV) unafafanua njia tatu za IPC, zinazojulikana kama SysV IPC:

  • Foleni za Ujumbe
  • Semaphores
  • Kumbukumbu iliyoshirikiwa

Kwa kuongezea hii, michakato inaweza kuingiliana kwa njia zingine, kama vile:

  • Soma, andika na uzuie ufikiaji wa faili
  • Ishara
  • Soketi
  • Vituo
  • FIFO (Wa kwanza Ndani, Wa Kwanza)

Kundi la mwisho mara nyingi hujulikana kama IPC. Makala haya yanaangazia mbinu za SysV IPC kutokana na urahisi na ufanisi wake.

Kuelewa Mfano wa SysV

Mbinu tatu za SysV IPC zina sintaksia sawa, ingawa madhumuni yake ni tofauti. Kwa kawaida unapaswa kufanya yafuatayo:

  1. Amua kitufe cha IPC kinachofaa kwa matumizi na ftok(3) .
  2. Toa kitambulisho mahususi cha IPC kinachohusishwa na ufunguo wa IPC kwa kutumia msgget(2) , semget(2) au shmget(2) kwa foleni za ujumbe, semaphores au kumbukumbu iliyoshirikiwa mtawalia.
  3. Badilisha sifa za mfano wa IPC kwa kutumia msgctl(2) , semctl(2) au shmctl(2) .
  4. Tumia mfano maalum wa IPC.
  5. Hatimaye, kuua mfano wa IPC ukitumia msgctl(2) , semctl(2) au shmctl(2) na bendera ya IPC_RMID.

Kila tukio la IPC linawakilishwa na kitambulishi ambacho husaidia kukitofautisha na matukio mengine ya IPC yaliyo katika mfumo fulani. Kwa mfano, kila moja ya programu mbili tofauti lazima itumie vizuizi vya kumbukumbu iliyoshirikiwa kwa Kitambulisho cha IPC cha mfumo mzima ili kutofautisha kati ya matukio hayo mawili. Huenda isiwe dhahiri, lakini changamoto kuu ni kuelewa jinsi ya kusambaza habari, kwa kuzingatia jinsi ya kuunganisha mchakato kwa mfano wa kawaida wa IPC, na sio kuweka utaratibu wa IPC kwanza.

Simu ya maktaba ya ftok hutumia habari ya ingizo kutoka kwa faili fulani na kitambulisho cha kipekee kuunda ufunguo ambao haubadiliki mradi tu faili iko na kitambulisho kinabaki sawa. Kwa njia hii, michakato miwili inaweza kutumia faili zao za usanidi na kukusanya vidhibiti vya wakati ili kuunda ufunguo sawa wa IPC. Uwepo wa vidhibiti huruhusu programu sawa kuunda hali nyingi za utaratibu wa IPC kwa kuzibadilisha.

Mara tu michakato mingi ikiwa na funguo za IPC tayari kwa kujitegemea, lazima zipate kitambulisho maalum kinachohusishwa na tukio maalum la IPC kupitia simu ya mfumo. Kupigiwa simu kunahitaji ufunguo wa IPC na seti ya bendera, pamoja na baadhi ya maelezo ya ukubwa wa semaphores na kumbukumbu iliyoshirikiwa. Kwa sababu UNIX ni mfumo wa watumiaji wengi, visanduku vya kuteua vinajumuisha ruhusa ya kufikia faili katika umbizo la kawaida la octal (kwa mfano, 666 inamaanisha mtu yeyote anaweza kusoma na kuandika faili). Ikiwa alama ya IPC_CREAT pia imewekwa, mfano wa IPC utaundwa ikiwa haipo. Ikiwa alama ya IPC_CREAT haijawekwa na mfano wa IPC haujaundwa, pokea simu itazalisha ujumbe wa hitilafu.

Kuna njia rahisi ya kuunda kitambulisho cha mfano cha IPC kwa programu hizo ambazo zinaweza kuifanya zenyewe. Ikiwa unatumia ufunguo wa IPC_PRIVATE unapopiga simu ili kuunda IPC, basi kitambulisho cha mfano kitakuwa cha kipekee. Michakato mingine inayohitaji kuunganishwa kwa IPC haihitaji kupiga simu kwa sababu tayari wana kitambulisho.

Maombi ni bure kutumia matukio ya IPC mradi tu yana kitambulisho. Kila njia ya IPC ni tofauti na nyingine na inapatikana tu katika sehemu yake.

Kupitisha ujumbe kwenye foleni

Foleni za ujumbe hutoa utaratibu unaoruhusu mchakato mmoja kuchapisha ujumbe ambao mchakato mwingine unaweza kupokea. Ujumbe unapopokelewa, huondolewa kwenye foleni. Foleni za ujumbe ni za kipekee kwa kuwa michakato yote miwili si lazima iendeshwe kwa wakati mmoja—mchakato mmoja unaweza kuchapisha ujumbe na kutoka, na ujumbe unaweza kupokelewa kwa mchakato mwingine siku kadhaa baadaye.

Ujumbe lazima uwe na nambari kamili ya ujumbe ikifuatwa na maudhui ya ujumbe. inaonyesha muundo sawa katika C kwa kutumia ujumbe wa baiti 100.

Kuorodhesha 1. Kufafanua sampuli ya ujumbe
struct mq_message ( aina ndefu; /* Aina au marudio */ maandishi ya char; /* Data */ );

Mpokeaji ujumbe hutumia aina ya ujumbe. Unapopokea ujumbe kutoka kwa foleni, unaweza kuchagua wa kwanza ujumbe unaopatikana au unaweza kupata aina fulani ujumbe. Aina za ujumbe wa kutumia ni mahususi wa programu kwa sababu huunda foleni, ambazo ni tofauti na aina zingine za IPC kwa kuwa kernel inatambua uhamishaji wa data ya programu kwa kusoma sehemu ya aina.

Inaonyesha mfano wa kupanga ujumbe.

Kuorodhesha 2. Programu inayopanga ujumbe kwenye foleni
#pamoja na #pamoja na #pamoja na #pamoja na #pamoja na int main (batili) ( key_t ipckey; int mq_id; struct ( aina ndefu; char text; ) mymsg; /* Tengeneza kitufe cha ipc */ ipckey = ftok("/tmp/foo", 42); printf("Funguo langu ni %d\n", ipckey); /* Sanidi foleni ya ujumbe */ mq_id = msgget(ipckey, IPC_CREAT | 0666); printf("Kitambulisho cha ujumbe ni %d\n", mq_id); /* Tuma ujumbe */ memset(mymsg.text, 0, 100); /* Futa nafasi */ strcpy(mymsg.text, "Hujambo, ulimwengu!"); mymsg.type = 1; msgsnd(mq_id, &mymsg, sizeof(mymsg) ), 0);)

Nambari katika kuingiza faili muhimu za kichwa na kisha kufafanua vigeu vya kutumika ndani kazi kuu. Hatua ya kwanza ni kuamua ufunguo wa IPC kwa kutumia /tmp/foo kama faili ya kawaida na nambari 42 kama kitambulisho. Ili kutazama nambari hii, printf(3c) inatumiwa kuonyesha nambari hii. Foleni ya ujumbe basi huundwa kwa kutumia msgget. Kigezo cha kwanza kwa msgget ni ufunguo wa IPC, na ya pili ni seti ya bendera. Katika mfano, bendera zina ruhusa za octal, zinazoruhusu mtu yeyote aliye na ufunguo wa IPC kutumia IPC hiyo kikamilifu, pamoja na bendera ya IPC_CREAT, ambayo huita msgget kuunda foleni. Tena, matokeo yanaonyeshwa kwenye skrini.

Kutuma ujumbe kwenye foleni ni rahisi. Baada ya kufuta nafasi ya kumbukumbu katika ujumbe kamba ya kawaida kunakiliwa kwa sehemu ya maandishi ya bafa. Aina ya ujumbe imedhamiriwa kuwa 1, na kisha msgsnd inaitwa. msgsnd inatarajia kupitishwa kitambulisho cha foleni, kielekezi kwa data, ukubwa wa data, na bendera inayoonyesha kama simu inapaswa kuzuiwa au la. Ikiwa alama ya IPC_NOWAIT imewekwa, simu itarudi hata kama foleni imejaa. Ikiwa bendera ni 0, basi simu imezuiwa hadi hakuna nafasi ya bure, foleni inafutwa au programu inapokea ishara.

Upande wa mteja wa equation hii hufanya kazi kwa njia sawa. Chini ni mfano wa msimbo unaorejesha ujumbe uliotumwa na seva.

Kuorodhesha 3. Msimbo wa kurejesha ujumbe kutoka kwa foleni
#pamoja na #pamoja na #pamoja na #pamoja na #pamoja na int main (batili) ( key_t ipckey; int mq_id; muundo ( aina ndefu; char text; ) mymsg; int imepokelewa; /* Tengeneza kitufe cha ipc */ ipckey = ftok("/tmp/foo", 42); printf( "Ufunguo wangu ni %d\n", ipckey); /* Sanidi foleni ya ujumbe */ mq_id = msgget(ipckey, 0); printf("Kitambulisho cha ujumbe ni %d\n", mq_id); kupokea = msgrcv( mq_id, &mymsg, sizeof(mymsg), 0, 0); printf("%s (%d)\n", mymsg.text, imepokelewa);)

Utaratibu wa kupata ufunguo wa IPC na kitambulisho cha foleni ya ujumbe ni sawa na msimbo wa seva. Simu ya msgget haifafanui alama zozote kwa sababu seva tayari imeunda foleni. Ikiwa programu ziliundwa ili mteja aweze kuanzishwa kabla ya seva, basi mteja na seva italazimika kufafanua ruhusa za ufikiaji na alama ya IPC_CREAT ili programu yoyote iliyoanza kabla ya zingine kuunda foleni.

mq_client.c kisha huita msgrcv kupata ujumbe kutoka kwa foleni. Vigezo vitatu vya kwanza vinafafanua kitambulisho cha foleni ya ujumbe, kielekezi kwa kiasi cha kumbukumbu ya ujumbe, na saizi ya bafa. Kigezo cha nne ni parameta ya aina, ambayo hukuruhusu kuchagua ni ujumbe gani wa kupokea:

  • Ikiwa aina ni 0, basi ujumbe wa kwanza kwenye foleni unarudishwa.
  • Ikiwa aina ni nambari kamili, basi ujumbe wa kwanza kwenye foleni na aina hiyo unarudishwa.
  • Ikiwa aina ni nambari hasi, ujumbe wa kwanza kwenye foleni unarudishwa ukiwa na thamani ya chini ambayo ni ndogo kuliko au sawa na thamani kamili ya aina inayofafanuliwa. Kwa mfano, ikiwa 2 na kisha 1 ziliongezwa kwenye foleni, kupiga msgrcv kwa aina -2 kungerudi 1 kwa sababu ndiyo ndogo zaidi, ingawa ni ya pili kwenye foleni.

Kigezo cha tano cha msgrcv tena ni bendera inayozuia. inaonyesha jinsi mteja na seva hufanya kazi.

Kuorodhesha 4. Matokeo ya mteja na msimbo wa seva
sunbox$ ./mq_server Ufunguo wangu ni 704654099 Kitambulisho cha ujumbe ni 2 sunbox$ ./mq_client Ufunguo wangu ni 704654099 Kitambulisho cha ujumbe ni 2 Hujambo, ulimwengu! (104)

Matokeo kutoka kwa mteja na seva yanaonyesha kuwa wote walipokea ufunguo sawa wa IPC kwa sababu walikuwa wakirejelea faili na kitambulisho sawa. Seva iliunda mfano wa IPC ambao kernel ilifafanua thamani 2, na programu ya mteja ilijua kuihusu. Kwa hiyo, haipaswi kushangaza kwamba mteja anapokea "Hello, dunia!" kutoka kwa foleni ya ujumbe.

Mfano huu unaonyesha hali rahisi zaidi. Foleni ya ujumbe inaweza kuwa muhimu kwa michakato ya muda mfupi, kama vile shughuli ya Wavuti ambayo inafafanua kazi kwa programu nzito ya nyuma, kama vile kutekeleza kundi la kazi. Mteja pia anaweza kuwa seva, na programu nyingi zinaweza kutuma ujumbe kwenye foleni. Sehemu ya aina ya ujumbe huruhusu programu kutuma ujumbe kwa wapokeaji mahususi.

Kufunga Rasilimali Kwa Kutumia Semaphores

Mawasiliano kati ya michakato sio lazima kuhusisha usambazaji kiasi kikubwa data. Kwa kweli, kidogo inaweza kutosha kuashiria kuwa mchakato unatumia aina fulani rasilimali maalum. Fikiria michakato miwili inayohitaji ufikiaji kwa baadhi vifaa, lakini ni moja tu ambayo inaweza kuitumia kwa wakati fulani. Wanaweza kubadilisha kwa kutumia counter. Ikiwa mchakato mmoja unasoma counter na kuona 1, basi ni wazi kwamba mchakato mwingine unatumia vifaa. Ikiwa thamani ya kaunta ni 0, basi mchakato unaweza kutumia maunzi mradi tu thamani ya kaunta iwe 1 wakati wa operesheni na thamani imewekwa upya hadi 0 operesheni inapokamilika.

Kuna matatizo mawili katika hali hii. Ya kwanza ni kuanzisha mita ya jumla na kuamua wapi itakuwa, ambayo ni usumbufu mkubwa zaidi. Tatizo la pili ni kwamba swala na shughuli za mgawo zinazohitajika ili kufunga rasilimali za maunzi sio atomiki. Ikiwa mchakato mmoja ungesoma thamani ya kaunta kama 0, lakini ikapitwa na mchakato mwingine kabla ya wa kwanza kuweka thamani ya kaunta kuwa 1, mchakato wa pili ungeweza kusoma na kugawa thamani ya kaunta. Michakato yote miwili ingezingatia kuwa wanaweza kutumia vifaa. Hakuna njia ya kujua ikiwa mchakato mwingine umetoa dhamana kwa kaunta. Inaitwa mbio za bahati. Semaphores kutatua matatizo haya yote mawili kwa kutoa interface ya kawaida kwa programu na kutumia jaribio la atomiki au operesheni ya mgawo.

Utekelezaji wa SysV wa semaphores ni wa jumla zaidi kuliko ule ulioelezewa hapo juu. Kwanza kabisa, thamani ya semaphore sio lazima iwe 0 au 1; inaweza kuwa 0 au nambari yoyote chanya. Pili, idadi ya shughuli zilizo na semaphores zinawezekana kwa namna sawa na aina ya parameter inayotumiwa na msgrcv . Shughuli hizi hupewa kama seti ya zana kwa kernel, na zinaendeshwa zote pamoja au haziendeshwi kabisa. Kernel inahitaji amri hizi zitolewe katika muundo unaoitwa sembuf, ambao ni pamoja na vifaa (kwa mpangilio):

  1. sem_num: maelezo ambayo semaphore katika seti inafanyiwa kazi.
  2. sem_op: Nambari kamili iliyotiwa saini iliyo na amri au jaribio la kutekelezwa.
  3. sem_flg: Mchanganyiko wa bendera ya kawaida ya IPC_NOWAIT, ambayo inaonyesha kama jaribio linafaa kuendeshwa mara moja au lizuiwe hadi likamilike, na SEM_UNDO, ambayo hughairi utendakazi wa semaphore ikiwa mchakato utaisha mapema.

sem_op ina idadi kubwa ya usanidi:

  • Ikiwa sem_op ni 0, basi sem_num inajaribiwa ili kuona kama thamani ni 0. Ikiwa sem_num ni 0, jaribio lifuatalo linafanywa. Ikiwa sem_num sio 0, operesheni itazuia hadi thamani ya semaphore iwe 0 na IPC_NOWAIT haijawekwa, au majaribio yaliyosalia yatarukwa ikiwa IPC_NOWAIT imewekwa.
  • Ikiwa sem_op ni nambari kamili, thamani ya sem_op huongezwa kwa thamani ya semaphore.
  • Ikiwa sem_op ni nambari hasi na thamani hasi ya semaphore ni kubwa kuliko au sawa na thamani kamili ya sem_op , basi thamani kamili inatolewa kutoka kwa thamani ya semaphore.
  • Ikiwa sem_op ni nambari hasi na thamani ya semaphore ni chini ya thamani kamili ya sem_op , basi majaribio yataacha mara moja ikiwa IPC_NOWAIT ni halali, au zuia hadi thamani ya semaphore iwe kubwa kuliko thamani kamili ya sem_op .

Mfano c hufafanua matumizi ya semaphores kwa kujaribu programu ambayo inaweza kuendeshwa mara nyingi kwa wakati mmoja, lakini inahakikisha kuwa mchakato mmoja tu ndio ulio katika sehemu muhimu kwa wakati mmoja. Toleo rahisi la semaphores hutumiwa; Rasilimali ni bure ikiwa thamani ya semaphore ni 0.

Kuorodhesha 5. Kutumia semaphore kulinda sehemu muhimu
#pamoja na #pamoja na #pamoja na #pamoja na /* Kwa strerror(3c) */ #jumuisha /* Kwa makosa */ #jumuisha /* rand(3c) */ #pamoja na int main (int argc, char **argv) ( key_t ipckey; int semid; muundo sembuf sem; /* sembuf inavyofafanuliwa katika sys/sem.h */ /* Tengeneza kitufe cha ipc */ ipckey = ftok("/tmp/ foo", 42); /* Sanidi seti ya semaphore. 4 == SOMA, 2 == ALTER */ semid = semget(ipckey, 1, 0666 | IPC_CREAT); ikiwa (nusu< 0) { printf("Error - %s\n", strerror(errno)); _exit(1); } /* These never change so leave them outside the loop */ sem.sem_num = 0; sem.sem_num = 0; sem.sem_flg = SEM_UNDO; /* Release semaphore on exit */ sem.sem_flg = SEM_UNDO; /* Release semaphore on exit */ while(1) { /* loop forever */ printf("[%s] Kusubiri semaphore itatolewa\n", argv); /* Sanidi shughuli mbili za semaphore */ sem.sem_op = 0; /* Subiri hadi sifuri */ sem.sem_op = 1; /* Ongeza 1 ili kuifunga*/ semop (semid, sem, 2); printf("[%s] Nina semaphore\n", argv); sleep(rand() % 3); /* Sehemu muhimu, lala kwa sekunde 0-2 */ sem. sem_op = -1; /* Punguzo la kufungua */ semop(semid, sem, 1); printf("[%s] Imetolewa semaphore\n", argv); lala(rand() % 3); /* Lala 0 Sekunde -2 */ ))

Inaonyesha mbinu kwa njia sawa na mfano wa foleni ya ujumbe. Kama vile msgget huamua ukubwa wa foleni ya ujumbe katika kigezo chake cha pili, semget huamua ukubwa wa seti ya semaphore. Seti ya semaphore ni kundi la semaphore zinazoshiriki mfano wa kawaida wa IPC. Idadi ya semaphores katika seti haiwezi kubadilishwa. Ikiwa seti ya semaphore imeundwa, basi parameter ya pili ya semget inapuuzwa. Ikiwa semget inarudisha nambari hasi inayoonyesha kutofaulu, sababu huchapishwa na programu hutoka.

Kabla ya kipindi kikuu cha wakati kitanzi, sem_num na sem_flg zimeanzishwa, kwani zinabaki thabiti katika mfano huu wote. SEM_UNDO inabainisha kuwa ikiwa mmiliki wa semaphore ataondoka kabla ya semaphore kutolewa, basi programu zingine zote hazitazuiwa.

Katika kitanzi hiki, ujumbe wa hali unachapishwa ili kuonyesha kwamba programu imeanza kusubiri semaphore. Ujumbe huu umetolewa na hoja ya mstari wa amri ya kwanza ili kuutofautisha na matukio mengine. Kabla ya kuingia sehemu muhimu, programu inafunga semaphore. Maagizo mawili ya semaphore yameandikwa. Ya kwanza ni 0, ambayo ina maana kwamba programu tumizi inasubiri hadi thamani ya semaphore imewekwa upya hadi 0. Ya pili ni 1, ikimaanisha kuwa baada ya kuweka upya thamani ya semaphore, 1 itaongezwa kwake. Programu huita semop kutekeleza amri, kupitisha amri zao. kitambulisho cha semaphore, pamoja na anwani ya muundo wa data na idadi ya amri za sembuf zitatumika.

Wakati semop inarudi, programu inajua kuwa imezuia semaphore na kuchapisha ujumbe kuonyesha hii. Sehemu muhimu kisha huanza, ambayo katika kesi hii inasimama kwa idadi isiyo ya kawaida ya sekunde. Semaphore hatimaye hutolewa kwa kuendesha amri moja ya sembuf yenye thamani ya semop ya -1, ambayo ina athari ya kutoa 1 kutoka kwa thamani ya semaphore na kuiweka upya hadi sifuri. Matokeo zaidi ya utatuzi huchapishwa, programu itasimama kwa muda fulani, na utekelezaji unaendelea. inaonyesha matokeo ya matukio mawili ya programu hii.

Kuorodhesha 6. Programu mbili zinazotumia semaphore kulinda sehemu muhimu
sunbox$ ./sem_example a & ./sem_example b & [a] Kusubiri semaphore kutolewa [a] Nina semaphore [b] Kusubiri semaphore kutolewa [a] Semaphore iliyotolewa [b] Nina semaphore [a] Kusubiri semaphore kutolewa [b] semaphore iliyotolewa [a] Nina semaphore [a] semaphore iliyotolewa [a] Kusubiri semaphore kutolewa [a] Nina semaphore

Huonyesha matukio mawili yanayoendeshwa, yanayoitwa a na b mtawalia. Kwanza a hupata semaphore na wakati huo huo b hujaribu kupata kufuli. Mara tu a inapotoa semaphore, b inapewa kufuli. Hali ni kinyume wakati a inasubiri b kukamilisha kazi yake. A huishia kukabidhi tena semaphore baada ya kujitenga nayo, kwani b haiko katika hali ya kungojea.

Jambo la mwisho la kutaja kuhusu semaphores ni kwamba zinajulikana kama kufuli zilizopendekezwa. Hii ina maana kwamba semaphores peke yake haizuii michakato miwili kutoka kwa kutumia rasilimali sawa kwa wakati mmoja; badala yake, zinahitajika ili kuonyesha kuwa rasilimali tayari zinatumika.

Kumbukumbu ya kawaida

Kumbukumbu inayoshirikiwa labda ndiyo mbinu ya IPC yenye nguvu zaidi ya SysV na rahisi zaidi kutekeleza. Kama jina linamaanisha, kizuizi cha kumbukumbu kinashirikiwa kati ya michakato mingi. inaonyesha mpango unaoita fork(2) kugawanyika katika michakato ya mzazi na mtoto inayowasiliana kwa kutumia sehemu kumbukumbu iliyoshirikiwa.

Kuorodhesha 7. Programu inayoonyesha matumizi ya kumbukumbu ya pamoja
#pamoja na #pamoja na #pamoja na #pamoja na #pamoja na #pamoja na int main(utupu) ( pid_t pid; int *imeshirikiwa; /* pointer kwa shm */ int shmid; shmid = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0666); ikiwa (uma() == 0) ( /* Mtoto */ /* Ambatanisha kwenye kumbukumbu iliyoshirikiwa na uchapishe pointer */ shared = shmat(shmid, (batili *) 0, 0); printf("Kielekezi cha mtoto %p\n", kimeshirikiwa); *imeshirikiwa=1 ; printf("Thamani ya mtoto=%d\n", *imeshirikiwa); lala(2); printf("Thamani ya mtoto=%d\n", *imeshirikiwa); ) vinginevyo ( /* Mzazi */ /* Ambatanisha kwa kumbukumbu iliyoshirikiwa na uchapishe pointer */ shared = shmat(shmid, (batili *) 0, 0); printf("Kielekezi cha mzazi %p\n", kilichoshirikiwa); printf("Thamani ya mzazi=%d\n", * pamoja); lala(1); *imeshirikiwa=42; printf("Thamani ya mzazi=%d\n", *imeshirikiwa); lala(5); shmctl(shmid, IPC_RMID, 0); ) )

Vigezo vya shmget vinapaswa kujulikana kwa sasa: ufunguo, ukubwa na bendera. Saizi ya kumbukumbu iliyoshirikiwa ndani katika mfano huu ni nambari moja kamili. hutofautiana na mifano ya awali katika matumizi ya IPC_PRIVATE kwa ufunguo wa IPC. IPC_PRIVATE inapotumika, kitambulisho cha kipekee cha IPC kinathibitishwa na programu inatarajiwa kutoa kitambulisho chenyewe. Katika mfano, shmid ni mchakato wa mzazi na mtoto kwa sababu ni nakala za kila mmoja. Simu ya mfumo wa uma hutoa nakala ya pili ya mchakato wa sasa, unaoitwa mtoto, ambao unafanana kikamilifu na mchakato wa mzazi. Taratibu zote mbili zinaendelea tena baada ya uma. Matokeo ya uma hutumiwa kuamua ikiwa mchakato wa sasa ni mzazi au mtoto.

Mchakato wa mzazi na mchakato wa mtoto unaonekana sawa. Kwanza, simu ya mfumo wa shmat hutumiwa kuhakikisha kuwa pointer inakaa katika sehemu ya kumbukumbu iliyoshirikiwa. shmat inahitaji kitambulisho cha kumbukumbu iliyoshirikiwa, kielekezi, na bendera kadhaa. Pointer hutumiwa kuomba anwani maalum ya kumbukumbu. Kwa kupitisha 0, kernel inaweza kuchagua chochote inachotaka. Bendera mara nyingi ni mahususi kwa muuzaji, hata hivyo SHM_RDONLY ni bendera ya kawaida inayoashiria kuwa sehemu hiyo haiwezi kuandikwa. Kama inavyoonyeshwa katika , shmat mara nyingi hutumiwa kuruhusu kernel kuamua kila kitu.

shmat inarudisha pointer kwenye sehemu iliyoshirikiwa, ambayo imechapishwa kwenye skrini kwa utatuzi. Kila mchakato basi hurekebisha sehemu ya kumbukumbu iliyoshirikiwa na kutoa thamani. Mwishowe, mchakato wa mzazi hufuta sehemu ya kumbukumbu iliyoshirikiwa kwa kutumia shmctl(2) . inaonyesha matokeo ya kutekeleza programu hii.

Kuorodhesha 8. Mfano wa pato la kumbukumbu iliyoshirikiwa
sunbox$ ./shared_memory Kielelezo cha mtoto ff390000 Thamani ya mtoto=1 Kielelezo cha mzazi ff380000 Thamani ya mzazi=1 Thamani ya mzazi=42 Thamani ya mtoto=42

Kulingana na data ya pato unaweza kuona kugawana eneo sawa la kumbukumbu iliyoshirikiwa. Kwanza, thamani ambayo mchakato wa mtoto umewekwa na kusoma na mchakato wa mzazi katika kumbukumbu iliyoshirikiwa ni 1. Kisha mchakato wa mzazi huweka thamani hadi 42, ambayo mchakato wa mtoto unasoma. Tambua kuwa michakato ya mzazi na mtoto ilikuwa na viashiria tofauti kwa anwani za sehemu ya kumbukumbu iliyoshirikiwa, ingawa walikuwa wanapata kumbukumbu sawa. Hili huleta tatizo kwa baadhi ya miundo ya data kama vile orodha zilizounganishwa wakati anwani halisi inatumiwa, kwa hivyo unaweza kutaka kutumia anwani inayolingana ikiwa unaunda miundo changamano katika kumbukumbu iliyoshirikiwa.

Mfano huu unategemea mchakato mmoja kusimamishwa wakati mwingine unaandika kwa sehemu ya kumbukumbu iliyoshirikiwa. Katika utumizi halisi, hii haitakuwa rahisi, kwa hivyo ikiwa programu yako ina michakato mingi ya kuandika kwa eneo moja la kumbukumbu, fikiria kufunga eneo hilo kwa kutumia semaphore.

Hitimisho

UNIX hutoa njia kadhaa za IPC. Mbinu za IPC za SysV ni foleni za ujumbe, taswira, na kumbukumbu iliyoshirikiwa. Foleni za ujumbe huruhusu programu moja kutuma ujumbe ambao programu zingine zinaweza kupokea baadaye, hata baada ya programu kukomesha. Semaphores huhakikisha kuwa programu tofauti zinaweza kufunga rasilimali na kuzuia mbio za serikali. Kumbukumbu iliyoshirikiwa inaruhusu maombi tofauti shiriki sehemu ya kumbukumbu ya kawaida, ambayo hutoa njia ya haraka ujumbe kati yao na uhamisho wa kiasi kikubwa cha data. Njia hizi zinaweza kutumika kwa pamoja. Kwa mfano, unaweza kutumia semaphore kudhibiti ufikiaji wa sehemu ya kumbukumbu iliyoshirikiwa.

Mbinu za IPC ni muhimu kwa wasanidi programu kwa sababu hutoa njia ya kawaida ya kuwasiliana kati ya programu na zinapatikana katika matoleo tofauti ya UNIX. Wakati mwingine unapohitaji kufunga rasilimali au kuhamisha data kati ya michakato, jaribu mifumo ya IPC ya SysV.

Katika vyumba vya upasuaji Mifumo ya Unix na Linux zina uwezo wa kuunda sehemu za kumbukumbu ambazo zinaweza kufikiwa na michakato mingi. Unapotumia zana hii, sehemu za nafasi ya anwani pepe michakato tofauti, zimechorwa kwa anwani sawa za kumbukumbu.

Wakati wa kufanya kazi na sehemu ya kumbukumbu iliyoshirikiwa, moja ya taratibu lazima kuunda sehemu ya kumbukumbu iliyoshirikiwa (ya kawaida), ikibainisha ukubwa wa sehemu inayohitajika, na kupata kitambulisho chake. Kitambulisho hiki basi kinatumiwa na mchakato wa muundaji kutekeleza shughuli za udhibiti kwenye kumbukumbu iliyoshirikiwa.

Baada ya kupokea kitambulisho cha sehemu ya kumbukumbu iliyoshirikiwa (kwa kuunda sehemu au kupokea kitambulisho chake kutoka kwa mchakato mwingine), mchakato lazima "uambatanishe" sehemu hiyo. Operesheni ya kiambatisho hurejesha anwani ya sehemu iliyoshirikiwa katika nafasi ya anwani pepe ya mchakato. Anwani pepe ya sehemu moja inaweza kuwa tofauti kwa michakato tofauti. Ifuatayo, michakato husoma na kuandika data katika sehemu ya kumbukumbu iliyoshirikiwa, kwa kutumia maagizo ya mashine sawa na wakati wa kufanya kazi na kumbukumbu ya kawaida.

Mchakato ambao umemaliza kufanya kazi na sehemu ya kumbukumbu iliyoshirikiwa lazima "iondoe", na wakati michakato yote imekamilika kutumia sehemu, lazima iharibiwe.

Wakati michakato inafanya kazi kwa wakati mmoja kwenye eneo la kumbukumbu iliyoshirikiwa, ufikiaji wao kwa eneo unaweza kuhitaji kusawazishwa. Kuhakikisha usawazishaji kama huo ni jukumu la mpangaji programu, ambaye anaweza kutumia algoriti kwa hii ambayo huondoa migongano ya upatanishi au zana za mfumo, kwa mfano, semaphores.

Simu za mfumo wa Unix/Linux

Utaratibu wa Unix/Linux OS wa sehemu za kumbukumbu zilizoshirikiwa hutolewa na simu nne za mfumo: shmget, shmctl, shmat, shmdt.

Simu ya mfumo shmctl hukuruhusu kufanya shughuli za udhibiti kwenye sehemu: pata habari kuhusu hali yake, ubadilishe haki za ufikiaji kwake, uharibu sehemu.

Simu za mfumo wa shmat na shmdt hufanya kiambatisho cha sehemu na kutenganisha, mtawalia.

Sehemu za kumbukumbu zilizoshirikiwa katika Unix/Linux (kama semaphores) hazina majina ya nje. Wakati wa kupata kitambulisho cha sehemu, mchakato hutumia ufunguo wa nambari. Watengenezaji wa michakato isiyohusiana wanaweza kukubaliana juu ya kawaida thamani muhimu, ambayo watatumia, lakini hawana uhakika kwamba thamani sawa ya ufunguo haitatumiwa na mtu mwingine. Sehemu ya kipekee iliyohakikishwa inaweza kuundwa kwa kutumia ufunguo wa IPC_PRIVATE, lakini ufunguo kama huo hauwezi kuwa kigeni. Kwa hivyo, sehemu hutumiwa, kama sheria, na michakato inayohusiana ambayo ina uwezo wa kuhamisha vitambulisho vyao kwa kila mmoja, kwa mfano, kupitia rasilimali zilizorithiwa au kupitia vigezo vya simu ya programu ya mtoto.

Makini!
Unapotatua programu, unaweza kukutana na hali ambapo programu huacha kufanya kazi au kuingiliwa na wewe kabla ya kuharibu maeneo ya kumbukumbu iliyoshirikiwa ambayo imeunda. Maeneo kama haya hayafutwa kiotomatiki na mfumo na yanaweza kujilimbikiza kwa siku nyingi. Mkusanyiko wa maeneo kama hayo "yaliyosahaulika" yanaweza kusababisha ukweli kwamba kikomo cha mfumo kwa idadi ya maeneo yaliyoshirikiwa kitakwisha, na simu nyingine.

Mawasiliano ya mwingiliano ( Mawasiliano kati ya mchakato (IPC)) ni seti ya njia za kubadilishana data kati ya nyuzi za mchakato. Taratibu zinaweza kuzinduliwa kwenye kompyuta moja na kwa zile tofauti zilizounganishwa na mtandao. IPC huja katika aina kadhaa: "signal", "soketi", "semaphore", "faili", "ujumbe"...

Katika nakala hii nataka kuangalia aina 3 tu za IPC:

Kichepuo: makala haya ni ya kielimu na yanalenga watu wanaoanza tu kwenye njia ya upangaji programu. Lengo lake kuu ni kujuana njia tofauti mwingiliano kati ya michakato kwenye OS inayoendana na POSIX.

Bomba lililopewa jina

Ili kusambaza ujumbe, unaweza kutumia soketi, njia, D-bus na teknolojia nyingine. Unaweza kusoma kuhusu soketi kwenye kila kona, na kuandika makala tofauti kuhusu D-bus. Kwa hiyo, niliamua kukaa juu ya teknolojia zisizojulikana zinazofikia viwango vya POSIX na kutoa mifano ya kazi.

Wacha tuangalie kupitisha ujumbe juu ya bomba zilizopewa jina. Kwa utaratibu uhamishaji unaonekana kama hii:

Ili kuunda bomba zilizopewa jina tutatumia kazi, mkfifo():
#pamoja na int mkfifo(const char *pathname, mode_t mode);
Kazi huunda faili maalum ya FIFO inayoitwa jina la njia, na kigezo hali inabainisha ruhusa za faili.

Kumbuka: hali kutumika pamoja na thamani ya sasa umask kwa njia ifuatayo: (hali& ~umask). Matokeo ya operesheni hii yatakuwa thamani mpya umask kwa faili tunayounda. Kwa sababu hii tunatumia 0777 ( S_IRWXO | S_IRWXG | S_IRWXU) ili usibadilishe sehemu yoyote ya mask ya sasa.
Mara faili inapoundwa, mchakato wowote unaweza kufungua faili kwa ajili ya kusoma au kuandika kama vile kufungua faili ya kawaida. Hata hivyo, kwa matumizi sahihi ya faili, ni muhimu kuifungua wakati huo huo kwa taratibu / nyuzi mbili, moja kupokea data (kusoma faili), nyingine kusambaza (kuandika kwenye faili).

Ikiwa faili ya FIFO imeundwa kwa ufanisi, mkfifo() inarudisha 0 (sifuri). Katika kesi ya makosa yoyote, chaguo la kukokotoa linarudi -1 na kuweka msimbo wa makosa kwa kutofautiana makosa.

Hitilafu za kawaida ambazo zinaweza kutokea wakati wa kuunda kituo:

  • EACCES- hakuna haki za kuendesha (kutekeleza) katika moja ya saraka kwenye njia jina la njia
  • EEXIST- faili jina la njia tayari ipo, hata kama faili ni kiungo cha mfano
  • ENOENT- hakuna saraka iliyotajwa ndani jina la njia, au ni kiungo kilichovunjika
  • ENOSPC- hakuna nafasi ya kuunda faili mpya
  • ENOTDIR- moja ya saraka zilizotajwa katika jina la njia, kwa kweli sivyo
  • EROFS- jaribu kuunda faili ya FIFO kwenye mfumo wa faili wa kusoma tu
Kusoma na kuandika kwa faili iliyoundwa hufanywa kwa kutumia kazi soma () Na andika().

Mfano

mkfifo.c
#pamoja na #pamoja na #pamoja na #pamoja na #fafanua NAMEDPIPE_NAME "/tmp/pipe_linalopewa" #fafanua BUFSIZE 50 int main (int argc, char ** argv) ( int fd, len; char buf; ikiwa (mkfifo(NAMEDPIPE_NAME, 0777)) ( perror("mkfifo") return 1; ) printf("%s imeundwa\n", NAMEDPIPE_NAME); ikiwa ((fd = fungua(NAMEDPIPE_NAME, O_RDONLY))<= 0) { perror("open"); return 1; } printf("%s is opened\n", NAMEDPIPE_NAME); do { memset(buf, "\0", BUFSIZE); if ((len = read(fd, buf, BUFSIZE-1)) <= 0) { perror("read"); close(fd); remove(NAMEDPIPE_NAME); return 0; } printf("Incomming message (%d): %s\n", len, buf); } while (1); } [скачать ]

Tunafungua faili ya kusoma tu ( O_RDONLY) Na inaweza kutumia O_NONBLOCK kirekebisho kilichoundwa mahsusi kwa faili za FIFO, ili usisubiri faili kufunguliwa kwa maandishi kwa upande mwingine. Lakini katika nambari iliyopewa njia hii haifai.

Tunakusanya programu, kisha kuiendesha:
$ gcc -o mkfifo mkfifo.c $ ./mkfifo
Katika dirisha la terminal linalofuata tunafanya:
$ echo "Hujambo, bomba langu linaloitwa!" > /tmp/my_named_pipe
Kama matokeo, tutaona matokeo yafuatayo kutoka kwa programu:
$ ./mkfifo /tmp/my_named_pipe imeundwa /tmp/my_named_pipe imefunguliwa Ujumbe unaoingia (22): Hujambo, bomba langu lililopewa jina! soma: Mafanikio

Kumbukumbu iliyoshirikiwa

Aina inayofuata ya mawasiliano ya mwingiliano ni kumbukumbu ya pamoja ( kumbukumbu iliyoshirikiwa) Wacha tuionyeshe kimkakati kama eneo fulani lililopewa jina kwenye kumbukumbu, ambalo hupatikana wakati huo huo na michakato miwili:


Ili kutenga kumbukumbu iliyoshirikiwa tutatumia kazi ya POSIX shm_fungua ():
#pamoja na int shm_open(const char *name, int oflag, mode_t mode);
Chaguo za kukokotoa hurejesha kielezi cha faili ambacho kinahusishwa na kitu cha kumbukumbu. Kifafanuzi hiki kinaweza kutumika baadaye na kazi zingine (kwa mfano, mmap() au kulinda ()).

Uadilifu wa kitu cha kumbukumbu hudumishwa, pamoja na data yote inayohusishwa nayo, hadi kitu hicho kimefungwa / kufutwa ( shm_unlink()) Hii inamaanisha kuwa mchakato wowote unaweza kufikia kitu chetu cha kumbukumbu (ikiwa kinajua jina lake) hadi tupige simu waziwazi shm_unlink().

Inaweza kubadilika lag ni ya busara kidogo AU ya bendera zifuatazo:

  • O_RDONLY- fungua tu na ruhusa za kusoma
  • O_RDWR- fungua kwa ruhusa ya kusoma na kuandika
  • O_CREAT- ikiwa kitu tayari kipo, basi bendera haina athari. Vinginevyo, kitu kinaundwa na haki za ufikiaji zimewekwa kwa ajili yake kwa mujibu wa mode.
  • O_EXCL- kuweka bendera hii pamoja na O_CREATE kutasababisha shm_open kurudisha hitilafu ikiwa sehemu ya kumbukumbu iliyoshirikiwa tayari ipo.
Jinsi thamani ya parameta imewekwa hali imeelezewa kwa undani katika aya iliyotangulia "kupitisha ujumbe".

Baada ya kuunda kitu cha kumbukumbu cha pamoja, tunaweka ukubwa wa kumbukumbu iliyoshirikiwa kwa kupiga simu ftruncate(). Ingizo la chaguo la kukokotoa ni kielezi cha faili cha kitu chetu na saizi tunayohitaji.

Mfano

Nambari ifuatayo inaonyesha kuunda, kurekebisha, na kufuta kumbukumbu iliyoshirikiwa. Inaonyesha pia jinsi baada ya kuunda kumbukumbu iliyoshirikiwa, programu inatoka, lakini wakati ujao tunapoianzisha tunaweza kuipata hadi itekelezwe. shm_unlink().
shm_fungua.c
#pamoja na #pamoja na #pamoja na #pamoja na #pamoja na #pamoja na #fafanua SHARED_MEMORY_OBJECT_NAME "kumbukumbu_iliyoshirikiwa" #fafanua SHARED_MEMORY_OBJECT_SIZE 50 #fafanua SHM_CREATE 1 #fafanua SHM_PRINT 3 #fafanua SHM_CLOSE 4 utumiaji batili(const char *f s" ["text"]\n", s); ) int main (int argc, char ** argv) ( int shm, len, cmd, mode = 0; char *addr; ikiwa (argc< 2) { usage(argv); return 1; } if ((!strcmp(argv, "create") || !strcmp(argv, "write")) && (argc == 3)) { len = strlen(argv); len = (len<=SHARED_MEMORY_OBJECT_SIZE)?len:SHARED_MEMORY_OBJECT_SIZE; mode = O_CREAT; cmd = SHM_CREATE; } else if (! strcmp(argv, "print")) { cmd = SHM_PRINT; } else if (! strcmp(argv, "unlink")) { cmd = SHM_CLOSE; } else { usage(argv); return 1; } if ((shm = shm_open(SHARED_MEMORY_OBJECT_NAME, mode|O_RDWR, 0777)) == -1) { perror("shm_open"); return 1; } if (cmd == SHM_CREATE) { if (ftruncate(shm, SHARED_MEMORY_OBJECT_SIZE+1) == -1) { perror("ftruncate"); return 1; } } addr = mmap(0, SHARED_MEMORY_OBJECT_SIZE+1, PROT_WRITE|PROT_READ, MAP_SHARED, shm, 0); if (addr == (char*)-1) { perror("mmap"); return 1; } switch (cmd) { case SHM_CREATE: memcpy(addr, argv, len); addr = "\0"; printf("Shared memory filled in. You may run "%s print" to see value.\n", argv); break; case SHM_PRINT: printf("Got from shared memory: %s\n", addr); break; } munmap(addr, SHARED_MEMORY_OBJECT_SIZE); close(shm); if (cmd == SHM_CLOSE) { shm_unlink(SHARED_MEMORY_OBJECT_NAME); } return 0; } [скачать ]

Baada ya kuunda kitu cha kumbukumbu, tunaweka ukubwa wa kumbukumbu iliyoshirikiwa tunayohitaji kwa kupiga simu ftruncate(). Kisha tulipata kumbukumbu iliyoshirikiwa kwa kutumia mmap(). (Kwa ujumla, hata na simu yenyewe mmap() unaweza kuunda kumbukumbu iliyoshirikiwa. Lakini tofauti ni wito shm_fungua () ni kwamba kumbukumbu itasalia kutengwa hadi ifutwe au kompyuta iwashwe upya.)

Wakati huu unahitaji kukusanya msimbo na chaguo -lrt:
$ gcc -o shm_open -lrt shm_open.c
Hebu tuone kilichotokea:
$ ./shm_open unda "Hujambo, kumbukumbu yangu iliyoshirikiwa!" Kumbukumbu iliyoshirikiwa imejazwa. Unaweza kuendesha "./shm_open print" ili kuona thamani. $ ./shm_open print Imetokana na kumbukumbu iliyoshirikiwa: Hujambo, kumbukumbu yangu iliyoshirikiwa! $ ./shm_open unda "Hujambo!" Kumbukumbu iliyoshirikiwa imejazwa. Unaweza kuendesha "./shm_open print" ili kuona thamani. $ ./shm_open print Umepokea kutoka kwa kumbukumbu iliyoshirikiwa: Hujambo! $ ./shm_open funga $ ./shm_open print shm_open: Hakuna faili au saraka kama hiyo
Katika programu yetu, tunatumia hoja ya "unda" kuunda kumbukumbu iliyoshirikiwa na kubadilisha yaliyomo.

Kujua jina la kitu cha kumbukumbu, tunaweza kubadilisha yaliyomo kwenye kumbukumbu iliyoshirikiwa. Lakini tunapaswa kupiga simu shm_unlink() jinsi kumbukumbu inavyoacha kupatikana kwetu na shm_fungua () bila parameter O_CREATE inarudisha kosa "Hakuna faili au saraka kama hiyo".

Semaphore

Semaphore ndio njia inayotumika sana kusawazisha nyuzi na kudhibiti ufikiaji kwa wakati mmoja kwa nyuzi/michakato nyingi kwa kumbukumbu iliyoshirikiwa (kwa mfano, tofauti ya kimataifa). Mwingiliano kati ya michakato katika kesi ya semaphores ni kwamba michakato hufanya kazi na seti sawa ya data na kurekebisha tabia zao kulingana na data hii.

Kuna aina mbili za semaphores:

  1. semaphore na kihesabu (kuhesabu semaphore), ambayo huamua kikomo cha rasilimali kwa michakato ya kuzifikia
  2. semaphore ya binary, ambayo ina majimbo mawili "0" au "1" (mara nyingi zaidi: " busy" au "haina shughuli")
Hebu tuangalie aina zote mbili za semaphores.

Semaphore na counter

Madhumuni ya semaphore na counter ni kutoa ufikiaji wa rasilimali fulani kwa idadi fulani ya michakato. Wengine watasubiri kwenye mstari hadi rasilimali itakapopatikana.

Kwa hivyo, kutekeleza semaphores tutatumia kazi ya POSIX sem_fungua():
#pamoja na sem_t *sem_open(const char *name, int oflag, mode_t mode, thamani ya int ambayo haijatiwa saini);
Kwa kazi ya kuunda semaphore tunapitisha jina la semaphore, iliyojengwa kulingana na sheria fulani, na bendera za udhibiti. Kwa njia hii tunapata semaphore inayoitwa.
Jina la semaphore limeundwa kama ifuatavyo: mwanzoni kuna herufi "/" (slash), ikifuatiwa na herufi za Kilatini. Tabia ya kufyeka haifai kutumika tena. Jina la semaphore linaweza kuwa na urefu wa hadi herufi 251.

Ikiwa tunahitaji kuunda semaphore, basi bendera ya udhibiti inapitishwa O_CREATE. Kuanza kutumia semaphore iliyopo tayari, basi lag sawa na sifuri. Ikiwa pamoja na bendera O_CREATE kupitisha bendera O_EXCL, kisha kazi sem_fungua() itarudisha hitilafu ikiwa semaphore iliyo na jina lililobainishwa tayari ipo.

Kigezo hali huweka haki za ufikiaji kwa njia sawa na ilivyoelezwa katika sura zilizopita. Tofauti thamani Thamani ya awali ya semaphore imeanzishwa. Chaguzi zote mbili hali Na thamani hupuuzwa ikiwa semaphore yenye jina lililobainishwa tayari ipo, na sem_fungua() aliita pamoja na bendera O_CREATE.

Ili kufungua haraka semaphore iliyopo, tunatumia ujenzi ufuatao:
#pamoja na sem_t *sem_open(const char *name, int oflag); , ambapo jina la semaphore pekee na bendera ya udhibiti imebainishwa.

Mfano wa semaphore na counter

Wacha tuangalie mfano wa kutumia semaphore kusawazisha michakato. Katika mfano wetu, mchakato mmoja huongeza thamani ya semaphore na kusubiri kwa pili ili kuiweka upya ili kuendelea na utekelezaji zaidi.
sem_fungua.c
#pamoja na #pamoja na #pamoja na #pamoja na #fafanua SEMAPHORE_NAME "/my_named_semaphore" int main(int argc, char ** argv) ( sem_t *sem; if (argc == 2) ( printf("Dropping semaphore...\n"); ikiwa ((sem = sem_open) (SEMAPHORE_NAME, 0)) == SEM_FAILED) ( kosa("sem_open"); rudisha 1; ) sem_post(sem); kosa("sem_post"); printf("Semaphore imeshuka.\n"); rudisha 0; ) ikiwa ((sem = sem_open(SEMAPHORE_NAME, O_CREAT, 0777, 0)) == SEM_FAILED) ( perror("sem_open"); rudisha 1; ) printf("Semaphore imechukuliwa.\nInasubiri idondoshwe.\n") ; ikiwa (sem_wait(sem)< 0) perror("sem_wait"); if (sem_close(sem) < 0) perror("sem_close"); return 0; } [скачать ]

Katika console moja tunaendesha:
$ ./sem_open Semaphore imechukuliwa. Inasubiri iangushwe.<-- здесь процесс в ожидании другого процесса sem_wait: Success sem_close: Success
Katika console inayofuata tunaendesha:
$ ./sem_open 1 Inadondosha semaphore... sem_post: Semaphore ya Mafanikio imeshuka.

Semaphore ya binary

Badala ya semaphore ya binary, ambayo kazi ya sem_open pia hutumiwa, nitazingatia semaphore inayotumiwa zaidi inayoitwa mutex.

Bubu kimsingi ni kitu sawa na semaphore ya binary (yaani semaphore iliyo na majimbo mawili: " busy" na "si busy"). Lakini neno "mutex" hutumiwa mara nyingi zaidi kuelezea mpango unaozuia michakato miwili kushiriki data/vigeu kwa wakati mmoja. Ingawa neno "semaphore ya binary" hutumiwa mara nyingi zaidi kuelezea muundo unaozuia ufikiaji wa rasilimali moja. Hiyo ni, semaphore ya binary hutumiwa ambapo mchakato mmoja "unachukua" semaphore, na mwingine "huitoa". Wakati bubu inatolewa na mchakato / uzi ule ule ambao uliichukua.

Huwezi kufanya bila bubu wakati wa kuandika, kwa mfano, hifadhidata ambayo inaweza kufikiwa na wateja wengi.

Ili kutumia mutex, unahitaji kupiga pthread_mutex_init() kazi:
#pamoja na Int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
Chaguo za kukokotoa huanzisha mutex (variable bubu) sifa mutexattr. Kama mutexattr sawa NULL, kisha bubu huanzishwa kwa thamani chaguo-msingi. Ikiwa chaguo la kukokotoa litatekelezwa kwa mafanikio (msimbo wa kurudisha 0), bubu inachukuliwa kuwa imeanzishwa na "isiyolipishwa".

Makosa ya kawaida ambayo yanaweza kutokea:

  • TENA- hakuna rasilimali muhimu za kutosha (isipokuwa kumbukumbu) ili kuanzisha bubu
  • ENOMEM- kumbukumbu haitoshi
  • EPERM- hakuna haki ya kufanya operesheni
  • EBUSY- jaribio la kuanzisha bubu ambayo tayari imeanzishwa lakini haijaharibiwa
  • EINVAL- maana mutexattr si halali
Ili kuchukua au kuachilia bubu, tunatumia kazi hizi:
int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);
Kazi pthread_mutex_lock(), Kama bubu bado haijashughulikiwa, anaichukua, anakuwa mmiliki wake na mara moja anaondoka. Ikiwa bubu ni busy, inazuia utekelezaji zaidi wa mchakato na inasubiri mutex kutolewa.
Kazi pthread_mutex_trylock() kufanana katika tabia na chaguo la kukokotoa pthread_mutex_lock(), isipokuwa moja - haizuii mchakato ikiwa bubu busy lakini anarudi EBUSY kanuni.
Kazi pthread_mutex_unlock() inatoa bubu yenye shughuli nyingi.

Rejesha misimbo ya pthread_mutex_lock():

  • EINVAL - mutex haijaanzishwa ipasavyo
  • EDEADLK - bubu tayari imechukuliwa na mchakato wa sasa
Rejesha misimbo ya pthread_mutex_trylock():
  • EBUSY - mutex tayari iko na shughuli nyingi
Rejesha misimbo ya pthread_mutex_unlock():
  • EINVAL - bubu haijaanzishwa kwa usahihi
  • EPERM - mchakato wa kupiga simu haumiliki bubu

Mfano bubu

bubu.c
#pamoja na #pamoja na #pamoja na #pamoja na static int counter; // rasilimali tuli ya pamoja pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void incr_counter(utupu *p) ( fanya ( usleep(10); // Hebu tuwe na kipande cha muda kati ya kufuli bubu pthread_mutex_lock(&mutex); counter++; printf("%d\n", counter); lala(1) ; pthread_mutex_unlock(&mutex); ) huku (1); ) utupu reset_counter(utupu *p) ( char buf; int num = 0; int rc; pthread_mutex_lock(&mutex); // zuia bubu ili kuonyesha ujumbe printf("Ingiza nambari na ubonyeze "Enter" ili kuanzisha kihesabu kwa thamani mpya wakati wowote.\n"); sleep(3); pthread_mutex_unlock(&mutex); // fungua mutex iliyozuiwa ili thread nyingine ifanye kazi ( if ( gets(buf) ) != buf) return; // HAKUNA ulinzi-mjinga ! Hatari ya kufurika ! num = atoi(buf); ikiwa ((rc = pthread_mutex_trylock(&mutex)) == EBUSY) ( printf("Mutex tayari imefungwa kwa mchakato mwingine.\nHebu "s lock mutex kwa kutumia pthread_mutex_lock().\n"); pthread_mutex_lock(&mutex); ) vinginevyo ikiwa (rc == 0) ( printf("WOW! Uko kwa wakati! Hongera!\n"); ) vinginevyo ( printf ("Hitilafu: %d\n", rc); return; ) counter = num; printf("Thamani mpya ya kaunta ni %d\n", kaunta); pthread_mutex_unlock(&mutex); ) wakati (1); ) int main(int argc, char ** argv) ( pthread_t thread_1; pthread_t thread_2; counter = 0; pthread_create(&thread_1, NULL, (batili *)&incr_counter, NULL); pthread_create(&thread_2, NULL, (batili_counter)" NULL); pthread_join(thread_2, NULL); rudisha 0; ) [pakua]

Mfano huu unaonyesha nyuzi mbili zinazoshiriki tofauti ya kawaida. Kamba moja (nyuzi ya kwanza) katika hali ya kiotomatiki huongeza kila kutofautisha kaunta kwa moja, huku nikichukua utaftaji huu kwa sekunde kamili. Uzi huu wa kwanza unatoa ufikiaji wa uzi wa pili kwa kutofautisha hesabu kwa milliseconds 10 tu, kisha ichukue tena kwa sekunde. Thread ya pili inakuhimiza kuingiza thamani mpya ya kutofautiana kutoka kwa terminal.

Ikiwa hatungetumia teknolojia ya mutex, hatujui ni thamani gani ingekuwa katika utofauti wa kimataifa na ufikiaji wa wakati mmoja kwa nyuzi mbili. Pia wakati wa kuanza tofauti kati ya pthread_mutex_lock() Na pthread_mutex_trylock().

Unahitaji kukusanya msimbo na parameter ya ziada - thread:
$ gcc -o bubu -lpthread mutex.c
Tunaanza na kubadilisha thamani ya kutofautisha kwa kuingiza thamani mpya kwenye dirisha la terminal:
$ ./mutex Ingiza nambari na ubonyeze "Enter" ili kuanzisha kihesabu kwa thamani mpya wakati wowote. 1 2 3 30 <--- новое значение переменной Mutex is already locked by another process. Let"s lock mutex using pthread_mutex_lock(). New value for counter is 30 31 32 33 1 <--- новое значение переменной Mutex is already locked by another process. Let"s lock mutex using pthread_mutex_lock(). New value for counter is 1 2 3

Badala ya hitimisho

Katika makala zifuatazo nataka kuangalia teknolojia za d-bus na RPC. Ikiwa una nia, nijulishe.
Asante.

UPD: Ilisasishwa sura ya 3 kuhusu semaphores. Imeongeza kifungu kidogo kuhusu mutex.

Lebo:

  • linux
  • nafasi
  • ipc
  • kupanga programu
Ongeza vitambulisho