Функции shared memory


Содержание

ЋЎй п (б®ў¬Ґбв­® ЁбЇ®«м§гҐ¬ п) Ї ¬пвм

Ћ¤Ё­ Ё§ б ¬ле Їа®бвле ¬Ґв®¤®ў ¬Ґ¦Їа®жҐбб®ў®Ј® ў§ Ё¬®¤Ґ©бвўЁп — ЁбЇ®«м§®ў вм ®Ўйго Ї ¬пвм. ЋЎй п Ї ¬пвм Ї®§ў®«пҐв ¤ўг¬ Ё«Ё Ў®«ҐҐ Їа®жҐбб ¬ ®Ўа й вмбп Є ®¤­®© Ё в®© ¦Ґ ®Ў« бвЁ Ї ¬пвЁ, Є Є Ўг¤в® ®­Ё ўбҐ ўл§лў «Ё malloc Ё Ё¬ Ўл«Ё ў®§ўа 饭л гЄ § ⥫Ё ­ ®¤­г Ё вг ¦Ґ дЁ§ЁзҐбЄго Ї ¬пвм. Љ®Ј¤ ®¤Ё­ Їа®жҐбб Ё§¬Ґ­пҐв Ї ¬пвм, ўбҐ ¤агЈЁҐ Їа®жҐббл «ўЁ¤пв» ¬®¤ЁдЁЄ жЁо.

Ѓлбв஥ «®Є «м­®Ґ ў§ Ё¬®¤Ґ©бвўЁҐ

ЋЎй п Ї ¬пвм — б ¬ п Ўлбва п д®а¬ ¬Ґ¦Їа®жҐбб®ў®Ј® ў§ Ё¬®¤Ґ©бвўЁп, Ї®в®¬г зв® ўбҐ Їа®жҐббл б®ў¬Ґбв­® ЁбЇ®«м§гов ®¤­г Ёвг ¦Ґ з бвм Ї ¬пвЁ. „®бвгЇ Є нв®© ®ЎйҐ© Ї ¬пвЁ ®бгйҐбвў«пҐвбп б в®© ¦Ґ бЄ®а®бвмо, зв® Ё ЇаЁ ®Ўа 饭ЁЁ Є ­Ґб®ў¬Ґбв­® ЁбЇ®«м§гҐ¬®© Ї ¬пвЁ, Ё нв® ­Ґ вॡгҐв бЁб⥬­®Ј® ўл§®ў Ё«Ё ўе®¤ ў п¤а®. ќв® в Є¦Ґ ­Ґ вॡгҐв Ё§«Ёи­ҐЈ® Є®ЇЁа®ў ­Ёп ¤ ­­ле.

Џ®бЄ®«мЄг п¤а® ­Ґ бЁ­еа®­Ё§ЁагҐв ¤®бвгЇл Є б®ў¬Ґбв­® ЁбЇ®«м§гҐ¬®© Ї ¬пвЁ, ўл ¤®«¦­л б ¬Ё ®ЎҐбЇҐзЁвм бЁ­еа®­Ё§ жЁо. Ќ ЇаЁ¬Ґа, Їа®жҐбб ­Ґ ¤®«¦Ґ­ зЁв вм Ё§ Ї ¬пвЁ, Ї®Є ¤ ­­лҐ ­Ґ § ЇЁб ­л вг¤ , Ё ¤ў Їа®жҐбб ­Ґ ¤®«¦­л ­ ЇЁб вм Ї® ®¤­®¬г Ё ⮬㠦Ґ ¤аҐбг Ї ¬пвЁ ў ®¤­® Ё в® ¦Ґ ўаҐ¬п. ЋЎй п бва ⥣Ёп Ё§ЎҐ¦ ­Ёп гб«®ўЁ© Ј®­ЄЁ б®бв®Ёв ў ⮬, зв®Ўл ЁбЇ®«м§®ў вм ᥬ д®ал.

Њ®¤Ґ«м Ї ¬пвЁ

—в®Ўл ЁбЇ®«м§®ў вм ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ, ®¤Ё­ Їа®жҐбб ¤®«¦Ґ­ ўл¤Ґ«Ёвм ᥣ¬Ґ­в. ’®Ј¤ Є ¦¤л© Їа®жҐбб, ¦Ґ« ойЁ© ®Ўа й вмбп Є ᥣ¬Ґ­вг ¤®«¦Ґ­ Ї®¤Є«озЁвм ᥣ¬Ґ­в. Џ®б«Ґ ®Є®­з ­Ёп ҐЈ® ЁбЇ®«м§®ў ­Ёп ᥣ¬Ґ­в , Є ¦¤л© Їа®жҐбб ®вЄ«оз Ґв ᥣ¬Ґ­в. ‚ ­ҐЄ®в®ал© ¬®¬Ґ­в, ®¤Ё­ Їа®жҐбб ¤®«¦Ґ­ ®бў®Ў®¤Ёвм ᥣ¬Ґ­в.

Џ®­Ё¬ ­ЁҐ ¬®¤Ґ«Ё Ї ¬пвЁ Linux Ї®¬®Ј Ґв ®Ўкпб­Ёвм Їа®жҐбб ўл¤Ґ«Ґ­Ёп Ё Ї®¤Є«о祭Ёп. Џ®¤ Linux , ўЁавг «м­ п Ї ¬пвм Є ¦¤®Ј® Їа®жҐбб а §ЎЁв ­ бва ­Ёжл. Љ ¦¤л© Їа®жҐбб Ї®¤¤Ґа¦Ёў Ґв ®в®Ўа ¦Ґ­ЁҐ ҐЈ® ¤аҐб®ў Ї ¬пвЁ ­ нвЁ бва ­Ёжл ўЁавг «м­®© Ї ¬пвЁ, Є®в®алҐ б®¤Ґа¦ в д ЄвЁзҐбЄЁҐ ¤ ­­лҐ. € е®вп Є ¦¤л© Їа®жҐбб Ё¬ҐҐв б®Ўб⢥­­лҐ ¤аҐб , ®в®Ўа ¦Ґ­Ёп ¬­®ЈЁе Їа®жҐбб®ў ¬®Јгв гЄ §лў вм ­ ®¤­г Ё вг ¦Ґ бва ­Ёжг, а §аҐи п б®ў¬Ґбв­®Ґ ЁбЇ®«м§®ў ­ЁҐ Ї ¬пвЁ.

‚뤥«Ґ­ЁҐ ­®ў®Ј® ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ ЇаЁў®¤Ёв Є ᮧ¤ ­Ёо бва ­Ёжл ўЁавг «м­®© Ї ¬пвЁ. Џ®бЄ®«мЄг ўбҐ Їа®жҐббл ¦Ґ« ов ®Ўа вЁвмбп Є ®¤­®¬г Ё ⮬㠦Ґ ®ЎйҐ¬г ᥣ¬Ґ­вг, в® в®«мЄ® ®¤Ё­ Їа®жҐбб ¤®«¦Ґ­ ўл¤Ґ«Ёвм ­®ўл© ®ЎйЁ© ᥣ¬Ґ­в. ‚뤥«Ґ­ЁҐ бгйҐбвўго饣® ᥣ¬Ґ­в ­Ґ ᮧ¤ Ґв ­®ўле бва ­Ёж, ў®§ўа й Ґв Ё¤Ґ­вЁдЁЄ в®а ¤«п бгйҐбвўгойЁе. —в®Ўл а §аҐиЁвм Їа®жҐббг ЁбЇ®«м§®ў вм ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ, Їа®жҐбб Ї®¤Є«оз Ґв ᥣ¬Ґ­в, Є®в®ал© ¤®Ў ў«пҐв ®в®Ўа ¦Ґ­ЁҐ ҐЈ® ўЁавг «м­®© Ї ¬пвЁ ­ ®ЎйҐ¤®бвгЇ­лҐ бва ­Ёжл ᥣ¬Ґ­в . Љ®Ј¤ а Ў®в б ᥣ¬Ґ­в®¬ § ўҐа襭 , нвЁ ®в®Ўа ¦Ґ­Ёп г¤ «повбп. Љ®Ј¤ ­Ё ®¤­Ё Ё§ Їа®жҐбб®ў ­Ґ е®зҐв ®Ўа й вмбп Є ᥣ¬Ґ­в ¬ ®ЎйҐ© Ї ¬пвЁ, Є Є®©-в® ®¤Ё­ Їа®жҐбб ¤®«¦Ґ­ ®бў®Ў®¤Ёвм бва ­Ёжл ўЁавг «м­®© Ї ¬пвЁ. ‚ᥠᥣ¬Ґ­вл ®ЎйҐ© Ї ¬пвЁ ўл¤Ґ«повбп Ї®бва ­Ёз­® Ё ®ЄагЈ«повбп ¤® а §¬Ґа бва ­Ёжл бЁб⥬л, Є®в®ал© пў«пҐвбп зЁб«®¬ Ў ©в®ў ў бва ­ЁжҐ Ї ¬пвЁ. Ќ бЁб⥬ е Linux , а §¬Ґа бва ­Ёжл а ўҐ­ 4 ЉЃ, ­® ўл ¤®«¦­л Ї®«гзЁвм нв® §­ 祭ЁҐ, ўл§лў п дг­ЄжЁо getpagesize .

‚뤥«Ґ­ЁҐ

Џа®жҐбб ўл¤Ґ«пҐв ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ, ЁбЇ®«м§гп shmget (» SHared Memory GET «). …Ј® ЇҐаўл© Ї а ¬Ґва — 楫®зЁб«Ґ­­л© Є«оз, Є®в®ал© ®ЇаҐ¤Ґ«пҐв, Є Є®© ᥣ¬Ґ­в ᮧ¤ вм. ЌҐбўп§ ­­лҐ Їа®жҐббл ¬®Јгв ®Ўа й вмбп Є ®¤­®¬г Ё ⮬㠦Ґ ᥣ¬Ґ­вг, ЁбЇ®«м§гп ®¤­® Ё в® ¦Ґ Є«о祢®Ґ §­ 祭ЁҐ. Љ ᮦ «Ґ­Ёо, ¤агЈЁҐ Їа®жҐббл, ў®§¬®¦­®, в Є¦Ґ ўлЎа «Ё в®в ¦Ґ б ¬л© Є«оз, зв® ¬®¦Ґв ЇаЁўҐбвЁ Є Є®­д«ЁЄвг. €бЇ®«м§гп бЇҐжЁ «м­го Є®­бв ­вг IPC_PRIVATE Є Є Є«о祢®Ґ §­ 祭ЁҐ, Ј а ­вЁагҐвбп, з⮠ᮧ¤ бвбп б®ўҐа襭­® ­®ўл© ᥣ¬Ґ­в Ї ¬пвЁ.

…Ј® ўв®а®© Ї а ¬Ґва ®ЇаҐ¤Ґ«пҐв зЁб«® Ў ©в®ў ў ᥣ¬Ґ­вҐ. Џ®бЄ®«мЄг ᥣ¬Ґ­вл ўл¤Ґ«повбп Ї®бва ­Ёз­®, зЁб«® д ЄвЁзҐбЄЁ ўл¤Ґ«Ґ­­ле Ў ©в ®ЄагЈ«пҐвбп ¤® а §¬Ґа бва ­Ёжл.

’аҐвЁ© Ї а ¬Ґва — Ї®а §ап¤­®Ґ ¤ў®Ёз­®Ґ Ё«Ё §­ 祭Ё© д« ¦Є , Є®в®алҐ ®ЇаҐ¤Ґ«пов ®ЇжЁЁ Є shmget . ‡­ 祭Ёп д« ¦Є ўЄ«оз ов в ЄЁҐ Ї а ¬Ґвал:

  • IPC_CREAT — нв®в д« ¦®Є гЄ §лў Ґв, зв® ¤®«¦Ґ­ Ўлвм ᮧ¤ ­ ­®ўл© ᥣ¬Ґ­в. ќв® а §аҐи Ґв ᮧ¤ ў вм ­®ўл© ᥣ¬Ґ­в, ®ЇаҐ¤Ґ«пп Є«оз.
  • IPC_EXCL — нв®в д« ¦®Є, Є®в®ал© ўбҐЈ¤ ЁбЇ®«м§гҐвбп б IPC_CREAT ,§ бв ў«пҐв shmget ў®§ўа й вм ®иЁЎЄг, Ґб«Ё ᥣ¬Ґ­в­л© Є«оз ®ЇаҐ¤Ґ«Ґ­, Є Є 㦥 бгйҐбвўгойЁ©. ќв® ЁбЇ®«м§гҐвбп ¤«п ўл¤Ґ«Ґ­Ёп «нЄбЄ«о§Ёў­®Ј®» ᥣ¬Ґ­в . …б«Ё нв®в д« ¦®Є ­Ґ ¤ Ґвбп, Ё Є«оз бгйҐбвўго饣® ᥣ¬Ґ­в ЁбЇ®«м§гҐвбп, shmget ў®§ўа й Ґв бгйҐбвўгойЁ© ᥣ¬Ґ­в ў¬Ґбв® в®Ј®, зв®Ўл ᮧ¤ вм ­®ўл©.
  • Mode flags — нв® §­ 祭ЁҐ Ё§ 9 ЎЁв®ў, гЄ §лў ойЁе Їа ў , ЇаҐ¤®бв ў«Ґ­­лҐ ў« ¤Ґ«мжг, ЈагЇЇҐ, Ё ¬Ёаг(®бв «м­л¬), ­ гЇа ў«Ґ­ЁҐ ¤®бвгЇ®¬ Є ᥣ¬Ґ­вг. ЃЁвл ўлЇ®«­Ґ­Ёп ЁЈ­®аЁаговбп. Џа®бв®© бЇ®б®Ў ®ЇаҐ¤Ґ«Ёвм Їа ў б®бв®Ёв ў ⮬, зв®Ўл ЁбЇ®«м§®ў вм Є®­бв ­вл, ®ЇаҐ¤Ґ«Ґ­­лҐ ў Ё ®ЇЁб ­лҐ ў а §¤Ґ«Ґ 2 stat man-бва ­Ёж . Ќ ЇаЁ¬Ґа, S_IRUSR Ё S_IWUSR ®ЇаҐ¤Ґ«пов Їа ў ­ з⥭ЁҐ Ё § ЇЁбм ¤«п ў« ¤Ґ«мж ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ, S_IROTH Ё S_IWOTH ®ЇаҐ¤Ґ«пов Їа ў ­ з⥭ЁҐ Ё § ЇЁбм ¤«п ¤агЈЁе.

Ќ ЇаЁ¬Ґа, нв®в ўл§®ў shmget ᮧ¤ Ґв ­®ўл© ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ (Ё«Ё ®Ўа й Ґвбп Є бгйҐбвўго饬г, Ґб«Ё shm_key 㦥 ЁбЇ®«м§гҐвбп), б Їа ў ¬Ё ­ зЁвҐ­ЁҐ Ё § ЇЁбм ў« ¤Ґ«м楬, ­® ­Ґ ¤агЈЁ¬Ё Ї®«м§®ў ⥫ﬨ.

…б«Ё ўл§®ў гᯥ襭, shmget ў®§ўа й Ґв Ё¤Ґ­вЁдЁЄ в®а ᥣ¬Ґ­в . …б«Ё ᥣ¬Ґ­в ®ЎйҐ© Ї ¬п⨠㦥 бгйҐбвўгҐв, в® Їа ў ­ ¤®бвгЇ Їа®ўҐаҐ­л, Ё Їа®ўҐаЄ Ј а ­вЁагҐв, з⮠ᥣ¬Ґ­в ­Ґ ®в¬ҐзҐ­ ¤«п г¤ «Ґ­Ёп.

Џ®¤Є«о祭ЁҐ Ё ®вЄ«о祭ЁҐ

—в®Ўл ᤥ« вм ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ ¤®бвгЇ­л¬, Їа®жҐбб ¤®«¦Ґ­ ЁбЇ®«м§®ў вм shmat , » SHared Memory ATtach » ЏҐаҐ¤ ©вҐ Ґ¬г Ё¤Ґ­вЁдЁЄ в®а ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ SHMID , ў®§ўа 饭­л© shmget . ‚в®а®© Ї а ¬Ґва — гЄ § ⥫м, Є®в®ал© ®ЇаҐ¤Ґ«пҐв, Ј¤Ґ ў ¤аҐб­®¬ Їа®бва ­б⢥ ў 襣® Їа®жҐбб ўл е®вЁвҐ ®в®Ўа §Ёвм ®Ўйго Ї ¬пвм; Ґб«Ё ўл ЇҐаҐ¤ ¤ЁвҐ NULL , в® Linux ўлЎҐаҐв «оЎ®© ¤®бвгЇ­л© ¤аҐб. ’аҐвЁ© Ї а ¬Ґва — д« ¦®Є, Є®в®ал© ¬®¦Ґв ўЄ«озЁвм б«Ґ¤гойЁҐ Ї а ¬Ґвал:

  • SHM_RND гЄ §лў Ґв, зв® ¤аҐб, ®ЇаҐ¤Ґ«Ґ­­л© ¤«п ўв®а®Ј® Ї а ¬Ґва , ¤®«¦Ґ­ Ўлвм ®ЄагЈ«Ґ­ ­ § ¤ Є ¬­®¦ЁвҐ«о а §¬Ґа бва ­Ёжл. …б«Ё ‚л ­Ґ ®ЇаҐ¤Ґ«пҐвҐ нв®в д« ¦®Є, ‚л ¤®«¦­л ўла®ў­пвм ­ Ја ­Ёжг бва ­Ёжл ўв®а®© Ї а ¬Ґва ЇҐаҐ¤ ў Ґ¬л© shmat б ¬®бв®п⥫쭮.
  • SHM_RDONLY гЄ §лў Ґв, з⮠ᥣ¬Ґ­в Ўг¤Ґв ¤®бвгЇҐ­ в®«мЄ® ¤«п з⥭Ёп.
  • ЃЁвл Їа ў ¤®бв Ї в ЄЁҐ ¦Ґ Є Є Ё ¤«п д ©«®ў.

…б«Ё ўл§®ў гᯥ襭, ®­ ўҐа­Ґв ¤аҐб Ї®¤Є«о祭­®Ј® ®ЎйҐЈ® ᥣ¬Ґ­в . Џ®в®¬ЄЁ, ᮧ¤ ­­лҐ ўл§®ў ¬Ё fork , ­ б«Ґ¤гов Ї®¤Є«о祭­лҐ ®ЎйЁҐ ᥣ¬Ґ­вл; ®­Ё ¬®Јгв ®вЄ«озЁвм ᥣ¬Ґ­вл ®ЎйҐ© Ї ¬пвЁ, Ґб«Ё § е®впв.

Љ®Ј¤ ўл § Є®­зЁ«Ё а Ў®вг б ᥣ¬Ґ­в®¬ ®ЎйҐ© Ї ¬пвЁ, ᥣ¬Ґ­в ¤®«¦Ґ­ Ўлвм ®вЄ«о祭, ЁбЇ®«м§гп shmdt (» SHared Memory DeTach «). ЏҐаҐ¤ ©вҐ Ґ¬г ¤аҐб, ў®§ўа 饭­л© shmat . …б«Ё ᥣ¬Ґ­в Ўл« ®бў®Ў®¦¤Ґ­, Ё Ў®«миҐ ­Ґ ®бв «®бм Їа®жҐбб®ў, ЁбЇ®«м§гойЁе ҐЈ®, ®­ Ўг¤Ґв г¤ «Ґ­. ‚맮ўл exit Ё exec ўв®¬ вЁзҐбЄЁ ®вЄ«оз ов ᥣ¬Ґ­вл.

“Їа ў«Ґ­ЁҐ Ё ®бў®Ў®¦¤Ґ­ЁҐ ®ЎйҐ© Ї ¬пвЁ

Shmctl (» SHared Memory ConTrol «) ўл§®ў ў®§ўа й Ґв Ё­д®а¬ жЁо ®Ў ᥣ¬Ґ­вҐ ®ЎйҐ© Ї ¬пвЁ Ё ¬®¦Ґв Ё§¬Ґ­Ёвм ҐЈ®.ЏҐаўл© Ї а ¬Ґва — Ё¤Ґ­вЁдЁЄ в®а ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ.

—в®Ўл Ї®«гзЁвм Ё­д®а¬ жЁо ® ᥣ¬Ґ­вҐ ®ЎйҐ© Ї ¬пвЁ, ЇҐаҐ¤ ©вҐ IPC_STAT Є Є ўв®а®© Ї а ¬Ґва Ё гЄ § вҐ«м ­ struct shmid_ds .

—в®Ўл г¤ «Ёвм ᥣ¬Ґ­в, ЇҐаҐ¤ ©вҐ IPC_RMID Є Є ўв®а®© Ї а ¬Ґва, Ё ЇҐаҐ¤ ©вҐ NULL Є Є ваҐвЁ© Ї а ¬Ґва. ‘ҐЈ¬Ґ­в г¤ «Ґ­, Є®Ј¤ Ї®б«Ґ¤­Ё© Їа®жҐбб, Є®в®ал© Ї®¤Є«озЁ« ҐЈ®, ®вЄ«озЁв ҐЈ®.

Љ ¦¤л© ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ ¤®«¦Ґ­ Ўлвм пў­® ®бў®Ў®¦¤Ґ­, ЁбЇ®«м§гп shmctl , Є®Ј¤ ‚л § Є®­зЁ«Ё а Ў®вг б ­Ё¬, зв®Ўл Ё§ЎҐ¦ вм ­ аг襭ЁҐ бЁб⥬­®Ј® ЇаҐ¤Ґ« а §¬Ґа Є®«ЁзҐб⢠ᥣ¬Ґ­в®ў ®ЎйҐ© Ї ¬пвЁ. ‚맮ўл exit Ё exec ®вЄ«оз в ᥣ¬Ґ­вл Ї ¬пвЁ, ­® ­Ґ ®бў®Ў®¦¤пв Ёе.

‘¬®ваЁ shmctl man-бва ­Ёжг ¤«п ®ЇЁб ­Ёп ¤агЈЁе ®ЇҐа жЁ©, Є®в®алҐ ¬®¦­® ўлЇ®«­пвм б ᥣ¬Ґ­в ¬Ё ®ЎйҐ© Ї ¬пвЁ.

ЏаЁ¬Ґа Їа®Ја ¬¬л

Џа®Ја ¬¬ «ЁбвЁ­Ј 5.1 Ё««обваЁагҐв ЁбЇ®«м§®ў ­ЁҐ ®ЎйҐ© Ї ¬пвЁ.

Љ®¬ ­¤ ipcs ЇаҐ¤®бв ў«пҐв Ё­д®а¬ жЁо ®в­®бЁвҐ«м­® б।бвў ў§ Ё¬®¤Ґ©бвўЁп Їа®жҐбб®ў, ўЄ«оз п ®ЎйЁҐ ᥣ¬Ґ­вл Ї ¬пвЁ. €бЇ®«м§г©вҐ д« Ј -m , зв®Ўл Ї®«гзЁвм Ё­д®а¬ жЁо ®Ў ®ЎйҐ© Ї ¬пвЁ. Ќ ЇаЁ¬Ґа, нв®в Є®¤ Ё««обваЁагҐв з⮠ᥣ¬Ґ­в ®ЎйҐ© Ї ¬пвЁ, Їа®­г¬Ґа®ў ­­л© 1627649, ­ 室Ёвбп ў ЁбЇ®«м§®ў ­ЁЁ:

…б«Ё нв®в ᥣ¬Ґ­в Ї ¬пвЁ Ўл« ®иЁЎ®з­® ®бв ў«Ґ­ Їа®Ја ¬¬®©, ўл ¬®¦ҐвҐ ЁбЇ®«м§®ў вм Є®¬ ­¤г ipcrm , зв®Ўл г¤ «Ёвм ҐЈ®.

‡ Ё Їа®вЁў

CҐЈ¬Ґ­вл ®ЎйҐ© Ї ¬пвЁ Ї®§ў®«пов ®бгйҐбвў«пвм Ўлбваго ¤ўг­ Їа ў«Ґ­­го бўп§м б।Ё «оЎ®Ј® зЁб« Їа®жҐбб®ў. Љ ¦¤л© Ї®«м§®ў вҐ«м ¬®¦Ґв Ё зЁв вм Ё ЇЁб вм, ­® Їа®Ја ¬¬ ¤®«¦­ гбв ­®ўЁвм Ё б«Ґ¤®ў вм ­ҐЄ®в®а®¬г Їа®в®Є®«г ¤«п в®Ј®, зв®Ўл ЇаҐ¤®вўа вЁвм гб«®ўЁп Ј®­ЄЁ вЁЇ ЇҐаҐ§ ЇЁбЁ Ё­д®а¬ жЁЁ ЇаҐ¦¤Ґ, 祬 ®­ Їа®зЁв Ґвбп. Љ ᮦ «Ґ­Ёо, Linux бва®Ј® ­Ґ Ј а ­вЁагҐв нЄбЄ«о§Ёў­л© ¤®бвгЇ ¤ ¦Ґ Ґб«Ё ўл ᮧ¤ ¤ЁвҐ ­®ўл© ®ЎйЁ© ᥣ¬Ґ­в б IPC_PRIVATE .

Ља®¬Ґ в®Ј®, ¤«п в®Ј® зв®Ў ­ҐбЄ®«мЄ® Їа®жҐбб®ў ¬®Ј«Ё ЁбЇ®«м§®ў вм ®Ўйго Ї ¬пвм, ®­Ё ¤®«¦­л ЇаЁ­пвм ¬Ґал, зв®Ўл ­Ґ ЁбЇ®«м§®ў вм ®¤Ё­ Ё в®в ¦Ґ Є«оз.

Функции Shared Memory

Shmop предлагает простой метод использования функций shared-памяти в PHP для чтения (read), записи (write), создания (create) и удаления сегментов Unix shared-памяти.

Примечание: Версии Windows до Windows 2000 по поддерживали shared-память. Под Windows, Shmop работает только когда PHP запускается как модуль веб-сервера, например, как модуль Apache или IIS (CLI и CGI не работают).

Примечание: В PHP 4.0.3, чаще имеют префикс shm , то есть реже, чем shmop .

Эти функции всегда доступны.

Для использования shmop Вам необходим PHP, скомпилированный с опцией —enable-shmop .

Данное расширение не определяет никакие директивы конфигурации в php.ini .

Данное расширение не определяет никакие константы.

Пример 1. Пример операций с Shared Memory

// Create 100 byte shared memory block with system id if 0xff3
$shm_id = shmop_open ( 0xff3 , «c» , 0644 , 100 );
if (! $shm_id ) <
echo «Couldn’t create shared memory segment\n» ;
>

// Get shared memory block’s size
$shm_size = shmop_size ( $shm_id );
echo «SHM Block Size: » . $shm_size . » has been created.\n» ;

// Lets write a test string into shared memory
$shm_bytes_written = shmop_write ( $shm_id , «my shared memory block» , 0 );
if ( $shm_bytes_written != strlen ( «my shared memory block» )) <
echo «Couldn’t write the entire length of data\n» ;
>

// Now lets read the string back
$my_string = shmop_read ( $shm_id , 0 , $shm_size );
if (! $my_string ) <
echo «Couldn’t read from shared memory block\n» ;
>
echo «The data inside shared memory was: » . $my_string . «\n» ;


//Now lets delete the block and close the shared memory segment
if (! shmop_delete ( $shm_id )) <
echo «Couldn’t mark shared memory block for deletion.» ;
>
shmop_close ( $shm_id );

Класс для работы с shared memory

01.10.2020, 17:26

Как хранить переменную типа char* в named shared memory section?
Во общем есть код: extern «C» __declspec(dllexport) void SetOptions(char* string); #pragma.

Shared memory
Микроконтроллер загружает необходимую информацию в shared memory по заранее известным адресам. Как.

Shared memory does not exist
Доброе утро! Столкнулся с такой проблемой, Oracle 8.1, лет 20 крутится около 18 схем и начала.

Pipe, fork, shared memory
Доброго времени суток. Помогите пожалуйста написать программу: Процесс читает с клавиатуры и пишет.

Creating Named Shared Memory
Здравствуйте. Пытаюсь освоить работу с общей памятью двух разных программ, используя FileMapping.

02.10.2020, 00:13 2

serega006, во-первых данный исходник не компилируется, из-за многочисленных ошибок.

во-вторых функции shmctl() и shmat() возвращают -1 в случае ошибки, используйте perror() для вывода текста ошибки. Так например, для первой у Вас неверное условие проверки результата функции.

Средства System V IPC. Организация работы с разделяемой памятью в UNIX. Понятие нитей исполнения (thread)

Разделяемая память в UNIX. Системные вызовы shmget(), shmat(), shmdt()

С точки зрения операционной системы, наименее семантически нагруженным средством System V IPC является разделяемая память (shared memory) . Мы уже упоминали об этой категории средств связи на лекции. Для текущего семинара нам достаточно знать, что операционная система может позволить нескольким процессам совместно использовать некоторую область адресного пространства. Внутренние механизмы , позволяющие реализовать такое использование, будут подробно рассмотрены на лекции, посвященной сегментной, страничной и сегментно-страничной организации памяти.

Все средства связи System V IPC требуют предварительных инициализирующих действий (создания) для организации взаимодействия процессов.

Для создания области разделяемой памяти с определенным ключом или доступа по ключу к уже существующей области применяется системный вызов shmget() . Существует два варианта его использования для создания новой области разделяемой памяти .

  • Стандартный способ. В качестве значения ключа системному вызову поставляется значение, сформированное функцией ftok() для некоторого имени файла и номера экземпляра области разделяемой памяти . В качестве флагов поставляется комбинация прав доступа к создаваемому сегменту и флага IPC_CREAT . Если сегмент для данного ключа еще не существует, то система будет пытаться создать его с указанными правами доступа. Если же вдруг он уже существовал, то мы просто получим его дескриптор. Возможно добавление к этой комбинации флагов флага IPC_EXCL . Этот флаг гарантирует нормальное завершение системного вызова только в том случае, если сегмент действительно был создан (т. е. ранее он не существовал), если же сегмент существовал, то системный вызов завершится с ошибкой, и значение системной переменной errno , описанной в файле errno.h , будет установлено в EEXIST .
  • Нестандартный способ. В качестве значения ключа указывается специальное значение IPC_PRIVATE . Использование значения IPC_PRIVATE всегда приводит к попытке создания нового сегмента разделяемой памяти с заданными правами доступа и с ключом, который не совпадает со значением ключа ни одного из уже существующих сегментов и который не может быть получен с помощью функции ftok() ни при одной комбинации ее параметров. Наличие флагов IPC_CREAT и IPC_EXCL в этом случае игнорируется.

Системный вызов shmget()

Прототип системного вызова

Описание системного вызова

Системный вызов shmget предназначен для выполнения операции доступа к сегменту разделяемой памяти и, в случае его успешного завершения, возвращает дескриптор System V IPC для этого сегмента (целое неотрицательное число, однозначно характеризующее сегмент внутри вычислительной системы и использующееся в дальнейшем для других операций с ним).

Параметр key является ключом System V IPC для сегмента, т. е. фактически его именем из пространства имен System V IPC . В качестве значения этого параметра может использоваться значение ключа, полученное с помощью функции ftok() , или специальное значение IPC_PRIVATE . Использование значения IPC_PRIVATE всегда приводит к попытке создания нового сегмента разделяемой памяти с ключом,который не совпадает со значением ключа ни одного из уже существующих сегментов и который не может быть получен с помощью функции ftok() ни при одной комбинации ее параметров.

Параметр size . определяет размер создаваемого или уже существующего сегмента в байтах. Если сегмент с указанным ключом уже существует, но его размер не совпадает с указанным в параметре size , констатируется возникновение ошибки.

Параметр shmflg – флаги – играет роль только при создании нового сегмента разделяемой памяти и определяет права различных пользователей при доступе к сегменту, а также необходимость создания нового сегмента и поведение системного вызова при попытке создания. Он является некоторой комбинацией (с помощью операции побитовое или – » | «) следующих предопределенных значений и восьмеричных прав доступа:

  • IPC_CREAT – если сегмента для указанного ключа не существует, он должен быть создан;
  • IPC_EXCL – применяется совместно с флагом IPC_CREAT . При совместном их использовании и существовании сегмента с указанным ключом, доступ к сегменту не производится и констатируется ошибочная ситуация, при этом переменная errno , описанная в файле , примет значение EEXIST ;
  • 0400 – разрешено чтение для пользователя, создавшего сегмент;
  • 0200 – разрешена запись для пользователя, создавшего сегмент;
  • 0040 – разрешено чтение для группы пользователя, создавшего сегмент;
  • 0020 – разрешена запись для группы пользователя, создавшего сегмент;
  • 0004 – разрешено чтение для всех остальных пользователей;
  • 0002 – разрешена запись для всех остальных пользователей.

Системный вызов возвращает значение дескриптора System V IPC для сегмента разделяемой памяти при нормальном завершении и значение -1 при возникновении ошибки.

Доступ к созданной области разделяемой памяти в дальнейшем обеспечивается ее дескриптором, который вернет системный вызов shmget() . Доступ к уже существующей области также может осуществляться двумя способами:

  • Если мы знаем ее ключ, то, используя вызов shmget() ,можем получить ее дескриптор. В этом случае нельзя указывать в качестве составной части флагов флаг IPC_EXCL , а значение ключа, естественно, не может быть IPC_PRIVATE . Права доступа игнорируются, а размер области должен совпадать с размером, указанным при ее создании.
  • Либо мы можем воспользоваться тем, что дескриптор System V IPC действителен в рамках всей операционной системы, и передать его значение от процесса, создавшего разделяемую память , текущему процессу. Отметим, что при создании разделяемой памяти с помощью значения IPC_PRIVATE – это единственно возможный способ.

После получения дескриптора необходимо включить область разделяемой памяти в адресное пространство текущего процесса. Это осуществляется с помощью системного вызова shmat() . При нормальном завершении он вернет адрес разделяемой памяти в адресном пространстве текущего процесса. Дальнейший доступ к этой памяти осуществляется с помощью обычных средств языка программирования.

Системный вызов shmat()

Прототип системного вызова


Описание системного вызова

Системный вызов shmat предназначен для включения области разделяемой памяти в адресное пространство текущего процесса. Данное описание не является полным описанием системного вызова, а ограничивается рамками текущего курса. Для полного описания обращайтесь к UNIX Manual.

Параметр shmid является дескриптором System V IPC для сегмента разделяемой памяти, т. е. значением, которое вернул системный вызов shmget() при создании сегмента или при его поиске по ключу.

В качестве параметра shmaddr в рамках нашего курса мы всегда будем передавать значение NULL , позволяя операционной системе самой разместить разделяемую память в адресном пространстве нашего процесса.

Параметр shmflg в нашем курсе может принимать только два значения: 0 – для осуществления операций чтения и записи над сегментом и SHM_RDONLY – если мы хотим только читать из него. При этом процесс должен иметь соответствующие права доступа к сегменту.

Системный вызов возвращает адрес сегмента разделяемой памяти в адресном пространстве процесса при нормальном завершении и значение -1 при возникновении ошибки.

После окончания использования разделяемой памяти процесс может уменьшить размер своего адресного пространства, исключив из него эту область с помощью системного вызова shmdt() . Отметим, что в качестве параметра системный вызов shmdt() требует адрес начала области разделяемой памяти в адресном пространстве процесса, т. е. значение , которое вернул системный вызов shmat() , поэтому данное значение следует сохранять на протяжении всего времени использования разделяемой памяти .

Системный вызов shmdt()

Прототип системного вызова

Описание системного вызова

Системный вызов shmdt предназначен для исключения области разделяемой памяти из адресного пространства текущего процесса.

Параметр shmaddr является адресом сегмента разделяемой памяти,т. е. значением, которое вернул системный вызов shmat() .

Системный вызов возвращает значение 0 при нормальном завершении и значение -1 при возникновении ошибки.

Прогон программ с использованием разделяемой памяти

Для иллюстрации использования разделяемой памяти давайте рассмотрим две взаимодействующие программы.

Эти программы очень похожи друг на друга и используют разделяемую память для хранения числа запусков каждой из программ и их суммы. В разделяемой памяти размещается массив из трех целых чисел. Первый элемент массива используется как счетчик для программы 1, второй элемент – для программы 2, третий элемент – для обеих программ суммарно. Дополнительный нюанс в программах возникает из-за необходимости инициализации элементов массива при создании разделяемой памяти . Для этого нам нужно, чтобы программы могли различать случай, когда они создали ее, и случай, когда она уже существовала. Мы добиваемся различия, используя вначале системный вызов shmget() с флагами IPC_CREAT и IPC_EXCL . Если вызов завершается нормально, то мы создали разделяемую память . Если вызов завершается с констатацией ошибки и значение переменной errno равняется EEXIST , то, значит, разделяемая память уже существует, и мы можем получить ее IPC дескриптор , применяя тот же самый вызов с нулевым значением флагов. Наберите программы, сохраните под именами 06-1а.с и 06-1b.c cоответственно, откомпилируйте их и запустите несколько раз. Проанализируйте полученные результаты.

Запись наборов данных в общую память с помощью PHP

Пошаговое руководство по использованию общей памяти PHP в качестве накопителя

Обзор

Общая память представляет собой эффективный способ обмена данными между приложениями в одной и той же машине. Один процесс создает сегмент общей памяти, к которому могут обращаться другие процессы, если у них есть нужные разрешения. Каждый сегмент получает уникальный идентификатор shmid, указывающий область физической памяти, где другие процессы могут работать с ним. После создания сегмент становится доступным для других процессов в той же машине, имеющих соответствующие разрешения, которые могут выполнять операции чтения, записи и удаления данных.

Это означает, что приложение, написанное на языке C, может обмениваться информацией с приложением, написанным на другом языке, таком как Java™ или PHP. Они могут обмениваться информацией, если только способны получить и понять эту информацию. Общая память широко применяется в реализациях, доступных для большинства языков, поэтому получение доступа не должно быть проблемой. Что касается понимания информации, то можно использовать стандартный формат, такой как XML или JSON.

Общая память представляет собой быстрый способ обмена данными между процессами, главным образом потому, что после создания сегментов ядро операционной системы не принимает никакого участия в процессе передачи данных. Подобные методы часто называют «межпроцессным взаимодействием» (interprocess communication — IPC). В число других методов IPC входят конвейеры, очереди сообщений, RPC и сокеты. Такой быстрый и надежный способ обмена данными между приложениями неоценим при работе с экосистемой приложений, которым нужно общаться друг с другом. Обычный метод использования баз данных для обмена информацией между приложениями часто приводит к медленной обработке запросов и даже блокированию ввода-вывода в зависимости от размера экосистемы. При работе с общей памятью операции ввода-вывода, замедляющие процесс, отсутствуют.

В этой статье предлагается простой способ создания и применения сегментов общей памяти с помощью PHP для хранения наборов данных, который могут использовать другие приложения. Даже не имея плана использования общей памяти для обмена данными, можно получить выгоду, потому что приложениям не нужно заниматься решением проблем ввода-вывода. Хранение наборов данных непосредственно в памяти имеет много преимуществ, от кэширования данных Web-сервисов до разделения сеансов. Это весьма полезная концепция, с которой должен быть знаком каждый PHP-разработчик.

Общая память и PHP

В PHP есть широкий набор расширений, в том числе для работы с общей памятью. Но разработчики могут легко манипулировать сегментами с помощью нескольких общих функций, не устанавливая никаких расширений.

Создание сегментов

Функции общей памяти аналогичны функциям управления файлами, только вместо потоков вы работаете с идентификаторами доступа к общей памяти. Первым примером служит функция shmop_open , которая позволяет открыть существующий или создать новый сегмент. Эта функция очень похожа на классическую функцию fopen , которая открывает потоки для манипуляции файлами, возвращая ресурс, доступный для использования другими функциями, выполняющими операции чтения или записи в этот открытый поток. Рассмотрим функцию shmop_open , приведенную в листинге 1.

Листинг 1. Функция shmop_open

Первый параметр ― system ID. Это число, определяющее сегмент общей памяти в системе. Второй параметр ― режим доступа, который очень похож на режим доступа функции fopen . Доступ к сегменту можно получить четырьмя способами:

  • режим «а» позволяет обращаться к сегменту только для чтения;
  • режим «w» позволяет обращаться к сегменту для чтения и записи;
  • в режиме «c» создается новый сегмент, а если он уже существует, предпринимается попытка открыть его для чтения и записи;
  • режим «n» создает новый сегмент, а если он уже существует, выдается сообщение об ошибке.

Третий параметр ― разрешения для сегмента. Здесь нужно указать восьмеричное число.

Четвертый параметр указывает размер сегмента в байтах. Прежде чем записывать данные в сегмент, необходимо выделить нужное количество байтов в нем.

Обратите внимание, что эта функция возвращает идентификационный номер, который можно использовать с другими функциями для манипулирования сегментом общей памяти. Это идентификатор доступа к общей памяти, отличный от системного идентификатора, передаваемого в качестве параметра. Не путайте их. В случае неудачи функция shmop_open возвратит значение FALSE.

Запись в сегменты

Для записи данных в блок общей памяти используйте функцию shmop_write . Она очень проста в применении и принимает всего три параметра. См. листинг 2.

Листинг 2. Применение функции shmop_write для записи в блок общей памяти

Она похожа на функцию fwrite , которая принимает два параметра: открытый ресурс потока, возвращаемый функцией fopen , и данные, подлежащие записи. Функция shmop_write делает то же самое.

Первый параметр — идентификатор, возвращаемый функцией shmop_open , ― определяет блок общей памяти, с которым вы собираетесь работать. Второй параметр — это данные, которые нужно хранить и, наконец, третий параметр определяет адрес начала записи. По умолчанию это 0, так что запись начинается с самого начала. В случае неудачи эта функция возвращает значение FALSE и количество успешно записанных байтов.

Чтение из сегментов

Чтение из сегментов общей памяти ― простая процедура. Достаточно открыть сегмент и воспользоваться функцией shmop_read . Она принимает несколько параметров и работает аналогично функции fread . В листинге 3 приведен пример чтения содержимого файла в PHP.

Листинг 3. Использование функции shmop_read для чтения содержимого файла

Чтение содержимого сегмента общей памяти выполняется аналогично, как показано в листинге 4.

Листинг 4. Чтение содержимого сегмента общей памяти

Обратите внимание на параметры. Функция shmop_read принимает идентификатор, возвращенный функцией shmop_open , который нам уже знаком, и два других параметра. Второй параметр ― место, с которого нужно начать чтение сегмента; а третий ― количество байтов, которое требуется считать. Второй параметр может всегда быть 0, началом данных, зато третий может вызвать проблему, так как мы можем не знать, сколько байтов хотим считать.

Это очень похоже на поведение функции fread , которая принимает два параметра: открытый ресурс потока, возвращаемый функцией fopen , и количество байтов, которые требуется считать из этого потока. Чтобы прочитать файл во всей его полноте, используйте функцию filesize , которая возвращает количество байтов в файле.

К счастью, при работе с сегментами общей памяти функция shmop_size , подобно функции filesize , возвращает размер сегмента в байтах. (См. листинг 5).


Листинг 5. Функция shmop_size возвращает размер сегмента в байтах

Удаление сегмента

Мы знаем, как открывать, записывать и считывать сегменты общей памяти. Для завершения нашего класса по CRUD осталось только узнать, как удалять сегменты. Эту задачу можно легко решить с помощью функции shmop_delete , которой нужен только один параметр: идентификатор сегмента общей памяти, который мы хотим удалить.

Листинг 6. Функция shmop_delete помечает сегмент для удаления

На самом деле она не удаляет сегмент. Она помечает его для удаления, поскольку сегмент общей памяти не может быть удален, пока существуют другие использующие его процессы. Функция shmop_delete помечает сегмент для удаления и мешает любому другому процессу открыть его. Теперь, чтобы удалить сегмент, его нужно закрыть.

Закрытие сегмента

При открытии сегмента общей памяти вы «присоединяетесь» к нему. Присоединившись к сегменту, в него можно записывать данные и считывать их из него, но когда работа закончена, нужно отсоединиться от сегмента. Это делается с помощью функции shmop_close , как показано в листинге 7.

Она очень похожа на функцию fclose при работе с файлами. После открытия потока с файлом и чтения или записи в него этот поток нужно закрыть, иначе произойдет блокировка.

Листинг 7. Использование функции shmop_close для отсоединения от сегмента

Использование общей памяти в качестве накопителя

Обладая базовыми знаниями в области общей памяти и освоив основные операции CRUD над сегментами общей памяти, можно приступать к практическому применению этих знаний. Общую память можно использовать в качестве уникальной альтернативы накопителю, которая предлагает такие преимущества, как быстрые операции чтения/записи и взаимодействие процессов. Для Web-приложения это означает:

  • буферную память (хранение запросов к базе данных, данных Web-сервисов, внешних данных);
  • память сеансов;
  • обмен данными между приложениями.

Прежде чем продолжить, я хотел бы представить небольшую библиотеку SimpleSHM. Это компактный уровень абстракции для работы с общей памятью в PHP, который позволяет легко манипулировать сегментами с применением объектно-ориентированного подхода. Эта библиотека помогает создавать гораздо более чистый код при написании небольших приложений, использующих общую память для хранения данных. Для начала работы с SimpleSHM загрузите tarball-файл со страницы GitHub.

Существует три вида операций: чтение, запись и удаление. Простое создание экземпляра объекта класса обеспечит открытие сегмента общей памяти. Основные моменты отражены в листинге 8.

Листинг 8. Основы использования SimpleSHM

Обратите внимание, что идентификатор классу не передается. Раз идентификатор не передается, номер будет выбран случайным образом, и новый сегмент откроется с этим номером. Номер можно передать конструктору в качестве параметра, чтобы сегмент открывался или создавался с конкретным значением ID, как показано в листинге 9.

Листинг 9. Открытие заданного сегмента

Магический метод __destructor заботится о вызове функции shmop_close по отношению к сегменту, чтобы отключить объект и отсоединить его от сегмента. Назовем это «SimpleSHM 101». Теперь воспользуемся им для более высокой цели: использования общей памяти в качестве накопителя. Для хранения наборов данных требуется сериализация, поскольку в памяти нельзя хранить массивы или объекты. Здесь для сериализации используется JSON, но подойдет и любой другой метод, например, XML или встроенные функции сериализации PHP. Пример приведен в листинге 10.

Листинг 10. Использование общей памяти в качестве накопителя

Мы успешно преобразовали массив в строку JSON, сохранили его в блоке общей памяти, считали, преобразовали строку JSON обратно в массив и отобразили его. Все это кажется тривиальным, но только представите себе, какие возможности открывает этот фрагмент. Его можно использовать для хранения результатов запросов к Web-сервису, базам данных или даже в качестве буфера процессора текстовых шаблонов. Запись и чтение из памяти обеспечит гораздо более высокую производительность, чем запись и чтение с диска.

Этот метод хранения полезен не только для использования в качестве буфера, но и для обмена данными между приложениями, если эти данные хранятся в формате, понятном обоим приложениям. Нельзя недооценивать возможности общей памяти в Web-приложениях. Существует множество различных способов эффективной реализации такого хранения, и единственное ограничение здесь ― талант и мастерство программиста.

Заключение

Эта статья охватывает большую часть инструментов PHP для работы с сегментами общей памяти и объясняет, как функционирует общая память. Более того, она содержит предложения по совершенствованию Web-приложений и обращает внимание на некоторые факторы, которые нужно иметь в виду при создании Web-приложений. Идеи и рекомендации по их осуществлению станут отправной точкой для читателя. А построенная нами базовая модель поможет ему обдумать более сложные функции и решения.

Что дальше?

Мы указали некоторые общие задачи, для решения которых идеально подходит общая память, такие как кэширование, совместное использование сеанса и обмен данными между приложениями. Это введение в работу с общей памятью открывает перед читателем возможности по исследованию гораздо более элегантных решений типичных задач. Не стесняйтесь расширять текущую реализацию SimpleSHM в соответствии со своими потребностями и вносить эти изменения в проект.

Ресурсы для скачивания

Похожие темы

  • Оригинал статьи: Store datasets directly in shared memory with PHP.
  • Книга Майкла Керриска Интерфейс программирования Linux содержит отличные главы о межпроцессном взаимодействии, а главы 45-48 посвящены IPC System V.
  • В статье Дэйва Маршалла IPC: общая память описан интересный и прагматический подход к функциям общей памяти на языке Си.
  • Книга Ричарда Стивенса Программирование сети UNIX содержит отличный технический материал и описание нескольких реализаций на языке C. Познакомьтесь с выдержкой из главы этой книги.
  • Следите за developerWorks в Твиттере.

Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

Shared Memory Functions

Table of Contents

  • shmop_close — Close shared memory block
  • shmop_delete — Delete shared memory block
  • shmop_open — Create or open shared memory block
  • shmop_read — Read data from shared memory block
  • shmop_size — Get size of shared memory block
  • shmop_write — Write data into shared memory block

User Contributed Notes 8 notes

I wrote a php memcache back in 2003 as a sort of proof of concept
it is use on a few machines for doing heavy page load caching.
it works very well.
Following are some of the core functions I made

###############################################
#### shared mem functions
/*
for debugging these
use `ipcs` to view current memory
use `ipcrm -m ` to remove
on some systems use `ipcclean` to clean up unused memory if you
don’t want to do it by hand
*/
###############################################
function get_key ( $fsize , $file ) <
if(! file_exists ( TMPDIR . TMPPRE . $file )) <
touch ( TMPDIR . TMPPRE . $file );
>
$shmkey = @ shmop_open ( ftok ( TMPDIR . TMPPRE . $file , ‘R’ ), «c» , 0644 , $fsize );
if(! $shmkey ) <
return false ;
>else <
return $shmkey ;
> //fi
>
function writemem ( $fdata , $shmkey ) <
if( MEMCOMPRESS && function_exists ( ‘gzcompress’ )) <
$fdata = @ gzcompress ( $fdata , MEMCOMPRESSLVL );
>
$fsize = strlen ( $fdata );
$shm_bytes_written = shmop_write ( $shmkey , $fdata , 0 );
updatestats ( $shm_bytes_written , «add» );
if( $shm_bytes_written != $fsize ) <
return false ;
>else <
return $shm_bytes_written ;
> //fi
>
function readmem ( $shmkey , $shm_size ) <
$my_string = @ shmop_read ( $shmkey , 0 , $shm_size );
if( MEMCOMPRESS && function_exists ( ‘gzuncompress’ )) <
$my_string = @ gzuncompress ( $my_string );
>
if(! $my_string ) <
return false ;
>else <
return $my_string ;
> //fi
>
function deletemem ( $shmkey ) <
$size = @ shmop_size ( $shmkey );
if( $size > 0 ) < updatestats ( $size , "del" ); >
if(!@ shmop_delete ( $shmkey )) <
@ shmop_close ( $shmkey );
return false ;
>else <
@ shmop_close ( $shmkey );
return true ;
>
>
function closemem ( $shmkey ) <
if(! shmop_close ( $shmkey )) <
return false ;
>else <
return true ;
>
>
function iskey ( $size , $key ) <
if( $ret = get_key ( $size , $key )) <
return $ret ;
>else <
return false ;
>
>
################################################
?>

Since there is no mention of the (lack of) need for locking here, I took a look into the shmop.c extensions code. So correct me if I’m wrong, but the shmop.c extension uses memcpy() to copy strings to and from shared memory without any form of locking, and as far as I know, memcpy() is not atomic.

If that’s true as I suspect, then these ‘easy to use’ functions are not so ‘easy to use’ any more and have to be wrapped in locks (e.g. semaphores, flocks, whatever).

I have written a script to highlight the superiority of shared memory storage.
Although it doesn’t use the shmop function, the underlying concept is similar.
‘/shm_dir/’ is a tmpfs directory, which is based on shared memory, that I have mounted on the server.

Below is the result on an Intel Pentium VI 2.8 server:

IO test on 1000 files
IO Result of Regular Directory : 0.079015016555786
IO Result of Shared Memory Directory : 0.047761917114258

IO test on 10000 files
IO Result of Regular Directory : 3.7090260982513
IO Result of Shared Memory Directory : 0.46256303787231

IO test on 40000 files
IO Result of Regular Directory : 117.35703110695 seconds
IO Result of Shared Memory Directory : 2.6221358776093 seconds

The difference is not very apparent nor convincing at 100 files.
But when we step it up a level to 10000 and 40000 files, it becomes pretty obvious that Shared Memory is a better contender.

// Your regular directory. Make sure it is write enabled
$setting [ ‘regular_dir’ ] = ‘/home/user/regular_directory/’ ;

// Your shared memory directory.
$setting [ ‘shm_dir’ ] = ‘/shm_dir/’ ;

// Number of files to read and write
$setting [ ‘files’ ] = 40000 ;

function IO_Test ( $mode )
<
$starttime = time ()+ microtime ();

for( $i = 0 ; $i $setting [ ‘files’ ] ; $i ++)
<
$filename = $setting [ $mode ]. ‘test’ . $i . ‘.txt’ ;
$content = «Just a random content» ;

// Just some error detection
if (! $handle = fopen ( $filename , ‘w+’ ))
<
echo «Can’t open the file » . $filename ;
exit;
>

if ( fwrite ( $handle , $content ) === FALSE )
<
echo «Can’t write to file : » . $filename ;
exit;
>

// Read Test
file_get_contents ( $filename );

$endtime = time ()+ microtime ();

$totaltime = ( $endtime — $starttime );

echo ‘IO test on ‘ . $setting [ ‘files’ ]. ‘ files
‘ ;
echo ‘IO Result of Regular Directory : ‘ . IO_Test ( ‘regular_dir’ ) . ‘ seconds
‘ ;
echo ‘IO Result of Shared Memory Directory : ‘ . IO_Test ( ‘shm_dir’ ) . ‘ seconds
‘ ;

/* Removal of files to avoid underestimation
#
# Failure to remove files will result in inaccurate benchmark
# as it will result in the IO_Test function not re-creating the existing files
*/
foreach ( glob ( $setting [ ‘regular_dir’ ]. «*.txt» ) as $filename ) <
unlink ( $filename ); $cnt ++;
>
foreach ( glob ( $setting [ ‘shm_dir’ ]. «*.txt» ) as $filename ) <
unlink ( $filename ); $cnt ++;
>

Разделяемая память

Подскажите, как реализовать разделяемую память через CreateFileMapping и MapViewOfFile . Нужно, чтобы было две программы, т.е. 2 запущенные консоли и между ними было взаимодействие. Т.е. клиент и сервер. Например, один печатает у себя, и у другого то же самое должно напечататься и наоборот.

3 ответа 3

Для таких целей разделяемая память не очень подходит, т.к. не имеет механизма уведомлений. Это именно что разделяемый кусок памяти, в который можно писать с разных процессов. Для целей указанных в вовпросе лучше подходят пайпа(pipes). На MSDN есть пример построения клиент-серверного приложения, т.е. как раз то, что Вам нужно.

А если всё таки очень хочется делать через разделяемую память, то на том же MSDN есть замечательный пример, как пользоваться функциями из вопроса. Вам же остается с одной стороны писать в разделяемый кусок, а с другой — проверять, на наличие новых данных. Или ввести некий синхронизирующий примитив, типа именованного семафора, чтобы не заниматься постоянной проверкой, которая отъедает ресурсы ЦП впустую.

Разделяемая память делается просто — вызовами CreateFileMapping и MapViewOfFile . Допустим у нас есть структура которая будет жить в общей памяти

Тогда мы создаем глобальный именованный объект общей памяти

и берем его память

Хендл mapping должен жить до конца работы с общей памятью. Если его закрыть, то память на которую указывает data останется жить, но будет отвязана от общей памяти.

Когда общая память будет не нужна — надо вызвать ::UnmapViewOfFile(data); и ::CloseHandle(mapping); , в любом порядке. (Или ExitProcess , при завершении процесса всё закрывается само).

Чтобы не вызывать их вручную, можно воспользоваться умными указателями:

Если запустить несколько процессов, то первый процесс вызвавший CreateFileMapping создаст глобальный объект, а остальные будут получать его хендл. Изменения data в одном процессе будут видны в остальных, но чтобы предотвратить гонки нужна какая-то синхронизация. В идеале нужен multiple readers/single-writer mutex и condition variable, но в Windows они не умеют работать с несколькими процессами, по этому все средства синхронизации надо писать самому. Реализация правильной межпроцессной синхронизации в Windows выходит за рамки этого вопроса, по этому в примере ниже будет использован обычный polling.

Linux: типы памяти

Виртуальная память (Virtual Memory)

В современных операционных системах каждый процесс выполняется в собственном выделенном ему участке памяти. Вместо отображения (mapping) адресов памяти непосредственно на физические адреса, операционная система работает как некий абстрактный слой, создавая виртуальное адресное пространство для каждого процесса. Процесс отображение адресов между физической памятью и виртуальной памятью выполняется процессором с использованием «таблицы трансляции» (translation table) (или «таблица страниц«, или «адресная таблица«, «таблица перевода«) для каждого процесса, которая поддерживается ядром системы (каждый раз, когда ядро изменяет процесс, выполняющийся процессором, он изменяет адресная таблицу этого процессора).

Концепция виртуальной памяти имеет несколько целей. Во-первых, она осуществляет изоляцию процессов. Процесс в своём адресном пространстве получает доступ памяти только как к адресам виртуальной памяти. Соответственно, он имеет доступ к данным, которые предварительно были отображены в его собственное виртуальное пространство, и не имеет доступа к памяти других процессов (если память или часть памяти другого процесса не является общей (shared memory)).

Вторая цель — абстракция физической памяти. Ядро может изменять адреса физической памяти, на которую отображена виртуальная память. Кроме того, ядро может вообще не выделять физическую память процессу, пока она действительно не понадобится. Так же, ядро может переместить часть памяти в swap , если она не используется продолжительное время. Всё вместе это даёт большую свободу ядру, и единственным ограничением для него является то, что когда процесс обращается к участку памяти — он должен найти там ту же информацию, которую он записал туда ранее.

Третья цель — возможность выделения адресов объектам, которые ещё не загружены в память. Это основной принцип, лежащий в основе вызова mmap() и отображения файлов в память (file-backend память). Вы можете выделить адрес в памяти для файла, и к нему можно будет обращаться как к любому объекту в памяти. Это очень полезная абстракция, которая помогает упростить код приложений и, в системах х64, и у вас имеется огромное пространство виртуальных адресов, в которое вы можете отобразить хоть всё содержимое вашего жёсткого диска.

Четвёртая цель использования виртуальной памяти — разделение (sharing) памяти для совместного использования процессами. Так как ядро знает, что процесс загружает в память, оно может избежать повторной загрузки объектов, и выделить новые адреса виртуальной памяти для другого процесса, которые будут отображены на те же адреса физической памяти, что и у другого процесса.

Результатом использования «разделяемой памяти» является появление механизма COW (copy-on-write): когда два процесса используют одну и ту же информацию, но один из них изменяет её и при этом второй процесс не имеет доступа на чтение изменившихся данных, ядро выполняет копирование этих данных. Недавно операционная система так же получила возможность определять идентичные данные в разлиных адресах памяти и автоматически отображать их на один и тот же адрес физической памяти. В Linux это называется KSM (Kernel SamePage Merging)

Наиболее часто используемым случаем COW является fork() . В Unix-like системах fork() является системным вызовом, который создаёт новый процесс методом копирования текущего. По кончании выполнения fork() , оба процесса продолжают свою работу с того же состояния, с теми же открытыми файлами и памятью. Благодаря COW, fork() не дублирует всю память процесса, когда «форкает» его, а использует новые адреса памяти только для тех данных, которые изменились родительским или дочерним процессом.

Кроме того, когда вызов fork() создаёт копию («снимок«, snapshot) памяти процесса — он потребляет на это очень мало системных ресурсов. Поэтому, если вы хотите выполнить какие-то операции над памятью процесса без риска потери «почвы под ногами», и при этом вы хотите избежать дорогостоящих (в плане ресурсов системы) действий или каких-то механизмов блокировок, которые могут содержать или приводить к ошибкам — просто используйте fork() , выполните вашу задачу и передайте рузультат её выполнения обратно к родительскому процессу (с помощью кода возврата, файла, через разделяемую память, каналы ( pipe ) и т.д.).

Этот механизм отлично работает, пока результаты выполнения задачи выполняются достаточно быстро, что бы большая часть памяти между родительским и дочерними процессами оставалась разделяемой (общей). Кроме того, это поможет писать более простой и читаемый код, так как все сложные задачи будут скрыты в ядре операционной системы, в коде системы виртуальной памяти, а не в вашем.

Страницы (pages)

Виртуальная память разделена на страницы. Размер одной страницы (прим.: не путайте с блоками (block),которые относятся к данным жесткого диска, тогда как страницы — к памяти) определяется процессором и обычно равен 4 КБ (килобайтам). Это означает, что управление памятью выполняется на уровне страниц, а не битах-байтах и т.д. Когда вы запрашиваете память у системы — ядро выделяет вам одну или более страниц, когда вы особождатете память — вы освобождаете одну или более страниц памяти.

Для каждой выделенной (allocated) страницы ядро устанавливает набор прав доступа (как с обычными файлами в файловой системе) — страница может быть доступна на чтение (readable), запись (writable) и/или выполнение (executable). Эти права доступа устанавливаются либо во время отображения (выделения) памяти, либо с помощью системного вызова mprotect() уже после выделения. Страницы, которые ещё не выделены недоступны. Когда вы попытаетесь выполнить недопустимое действие над страницей памяти (например — считать данные со страницы, у которой не установлено право на чтение) — вы вызовете исключение Segmentation Fault .

Типы памяти (memory types)

Не вся память, выделенная в виртуальном пространстве, одинаковая. Мы можем классифицировать память по двум «осям»: первая — является ли память частной (private), т.е. специфичной для процесса, или общей (shared), и вторая ось — является ли память file-backed или нет (в таком случае — она является «анонимной» (anonymous) памятью). Таким образом — мы можем создать 4 класса памяти:

Creating Named Shared Memory

To share data, multiple processes can use memory-mapped files that the system paging file stores.

First Process

The first process creates the file mapping object by calling the CreateFileMapping function with INVALID_HANDLE_VALUE and a name for the object. By using the PAGE_READWRITE flag, the process has read/write permission to the memory through any file views that are created.

Then the process uses the file mapping object handle that CreateFileMapping returns in a call to MapViewOfFile to create a view of the file in the process address space. The MapViewOfFile function returns a pointer to the file view, pBuf . The process then uses the CopyMemory function to write a string to the view that can be accessed by other processes.

Prefixing the file mapping object names with «Global\» allows processes to communicate with each other even if they are in different terminal server sessions. This requires that the first process must have the SeCreateGlobalPrivilege privilege.

When the process no longer needs access to the file mapping object, it should call the CloseHandle function. When all handles are closed, the system can free the section of the paging file that the object uses.

Second Process

A second process can access the string written to the shared memory by the first process by calling the OpenFileMapping function specifying the same name for the mapping object as the first process. Then it can use the MapViewOfFile function to obtain a pointer to the file view, pBuf . The process can display this string as it would any other string. In this example, the message box displayed contains the message «Message from first process» that was written by the first process.

shared memory

Англо-русский толковый словарь терминов и сокращений по ВТ, Интернету и программированию. . 1998-2007 .

Смотреть что такое «shared memory» в других словарях:

Shared Memory — (dt. „gemeinsam genutzter Speicher“) wird in der Computertechnologie verwendet und kann dabei je nach Kontext eine andere Technologie beschreiben: Shared Memory in der Interprozesskommunikation (IPC): Hier nutzen zwei oder mehrere Prozesse einen… … Deutsch Wikipedia

Shared memory — (dt. „geteilter Speicher“) bezeichnet eine bestimmte Art der Interprozesskommunikation (IPC). Bei dieser Art nutzen zwei oder mehrere Prozesse einen bestimmten Teil des Hintergrundspeichers (RAM) gemeinsam. Für alle beteiligten Prozesse liegt… … Deutsch Wikipedia

Shared Memory — [dt. »geteilter Speicher«], ein Bereich des Arbeitsspeichers, der von mehreren Benutzern oder Prozessen gemeinsam genutzt werden kann. Bei kleinen Netzwerken mit Nutzung von Groupware kann sich der Begriff auch auf die Nutzung der… … Universal-Lexikon

Shared memory — In computing, shared memory is a memory that may be simultaneously accessed by multiple programs with an intent to prov >Wikipedia

shared memory — bendroji atmintis statusas T sritis informatika apibrėžtis ↑Atminties sritis, kurią bendrai naudoja keli procesai duomenų mainams. Per ją vyksta duomenų mainai tarp procesų. atitikmenys: angl. shared memory ryšiai: dar žiūrėk – atmintis palygink… … Enciklopedinis kompiuterijos žodynas

shared memory — An interprocess communications technique in which the same memory is accessed by more than one program running in a multitasking operating system. Semaphores or other management elements prevent the applications from coll >Dictionary of networking

shared memory — Portion of memory accessible to multiple processes … IT glossary of terms, acronyms and abbreviations

Shared Memory Architecture — In computer architecture, Shared Memory Architecture (SMA) refers to a design where the graphics chip does not have its own dedicated memory, and instead shares the main system RAM with the CPU and other components. This design is used with many… … Wikipedia

Distributed shared memory — (DSM), in Computer Architecture is a form of memory architecture where the (physically separate) memories can be addressed as one (logically shared) address space. Here, the term shared does not mean that there is a single centralized memory but… … Wikipedia

Distributed Shared Memory — (verteilter gemeinsamer Speicher, DSM) ist ein Ausdruck aus der Informatik und bezieht sich auf die Verteilung des Arbeitsspeichers von Computerclustern. Da sich die einzelnen CPUs nicht auf einem gemeinsamen Mainboard befinden, existiert auch… … Deutsch Wikipedia

Virtual shared memory — Als Virtual Shared Memory bzw. virtueller Gemeinspeicher bezeichnet man eine Technik zur Verwendung gemeinsamer Speicherbereiche in Computernetzwerken oder Computerclustern. Dabei muss der gemeinsame Speicher nicht physikalisch existieren,… … Deutsch Wikipedia

Илон Маск рекомендует:  Псевдокласс last-child в CSS
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL