Datoros, lai process būtu izpildāms, tas ir jāievieto atmiņā. Šim nolūkam procesam atmiņā ir jāpiešķir lauks. Atmiņas piešķiršana ir svarīga problēma, kas jāapzinās, jo īpaši kodola un sistēmas arhitektūrā.
Sīkāk apskatīsim Linux atmiņas piešķiršanu un sapratīsim, kas notiek aizkulisēs.
Kā tiek veikta atmiņas piešķiršana?
Lielākā daļa programmatūras inženieru nezina šī procesa detaļas. Bet, ja esat sistēmas programmētāja kandidāts, jums par to vajadzētu uzzināt vairāk. Aplūkojot piešķiršanas procesu, ir jāiedziļinās nedaudz detaļās par Linux un glibc bibliotēka.
Ja lietojumprogrammām ir nepieciešama atmiņa, tā ir jāpieprasa no operētājsistēmas. Šim pieprasījumam no kodola, protams, būs nepieciešams sistēmas izsaukums. Lietotāja režīmā pats nevar piešķirt atmiņu.
The malloc () funkciju saime ir atbildīga par atmiņas piešķiršanu C valodā. Šeit jāuzdod jautājums, vai malloc () kā glibc funkcija veic tiešu sistēmas izsaukumu.
Linux kodolā nav sistēmas izsaukuma malloc. Tomēr ir divi sistēmas aicinājumi lietojumprogrammām atmiņas prasībām, kas ir brk un mmap.
Tā kā jūs savā lietojumprogrammā pieprasīsit atmiņu, izmantojot glibc funkcijas, iespējams, jums rodas jautājums, kuru no šiem sistēmas izsaukumiem glibc izmanto šobrīd. Atbilde ir gan.
Pirmais sistēmas zvans: brk
Katram procesam ir blakus datu lauks. Ar brk sistēmas izsaukumu tiek palielināta programmas pārtraukuma vērtība, kas nosaka datu lauka robežu un tiek veikts piešķiršanas process.
Lai gan atmiņas piešķiršana ar šo metodi ir ļoti ātra, ne vienmēr ir iespējams sistēmā atgriezt neizmantoto vietu.
Piemēram, ņemiet vērā, ka jūs piešķirat piecus laukus, katrs 16 KB lielu, ar brk sistēmas izsaukumu, izmantojot funkciju malloc(). Kad esat pabeidzis ar otro numuru no šiem laukiem, nav iespējams atgriezt attiecīgo resursu (atdalīšanu), lai sistēma to varētu izmantot. Jo, ja jūs samazināt adreses vērtību, lai parādītu vietu, kur sākas jūsu lauks numurs 2, ar izsaukumu uz brk, jūs būsiet veicis trešo, ceturto un piekto lauku izvietošanu.
Lai novērstu atmiņas zudumu šajā scenārijā, malloc implementācija glibc uzrauga procesa datu laukā piešķirtās vietas un pēc tam norāda, lai to atgrieztu sistēmai ar funkciju free(), lai sistēma varētu izmantot brīvo vietu turpmākai atmiņai piešķīrumi.
Citiem vārdiem sakot, pēc pieciem 16 KB apgabaliem tiek piešķirti, ja tiek atgriezts otrais apgabals ar funkciju free() un vēl 16 KB apgabals pēc kāda laika tiek pieprasīts vēlreiz, tā vietā, lai palielinātu datu apgabalu, izmantojot brk sistēmas izsaukumu, tiek atgriezta iepriekšējā adrese.
Tomēr, ja no jauna pieprasītais apgabals ir lielāks par 16 KB, datu apgabals tiks palielināts, piešķirot jaunu apgabalu ar brk sistēmas izsaukumu, jo otro apgabalu nevar izmantot. Lai gan otrais apgabals netiek izmantots, lietojumprogramma to nevar izmantot lieluma atšķirības dēļ. Šādu scenāriju dēļ pastāv situācija, ko sauc par iekšējo sadrumstalotību, un patiesībā jūs reti varat pilnībā izmantot visas atmiņas daļas.
Lai labāk izprastu, mēģiniet apkopot un palaist šādu lietojumprogrammas paraugu:
#iekļauts <stdio.h>
#iekļauts <stdlib.h>
#iekļauts <unistd.h>
starptgalvenais(starpt argc, char* argv[])
{
char *ptr[7];
starpt n;
printf("%s Pid: %d", argv[0], getpid());
printf("Sākotnējais programmas pārtraukums: %p", sbrk (0));
priekš (n=0; n<5; n++) ptr[n] = malloc (16 * 1024);
printf("Pēc 5 x 16 kB malloc: %p", sbrk (0));
bezmaksas(ptr[1]);
printf("Pēc brīvā no otrās 16kB: %p", sbrk (0));
ptr[5] = malloc (16 * 1024);
printf("Pēc 6. no 16 kB piešķiršanas: %p", sbrk (0));
bezmaksas(ptr[5]);
printf("Pēc pēdējā bloka atbrīvošanas: %p", sbrk (0));
ptr[6] = malloc (18 * 1024);
printf("Pēc jauna 18kB piešķiršanas: %p", sbrk (0));
getchar();
atgriezties0;
}
Palaižot lietojumprogrammu, jūs saņemsit rezultātu, kas līdzīgs šādai izvadei:
Pid of ./a.out: 31990
Sākotnējā programma pārtraukums: 0x55ebcadf4000
Pēc 5 x 16 kB malloc: 0x55ebcadf4000
Pēc brīva no otrā 16 kB: 0x55ebcadf4000
Pēc 6. no 16 kB piešķiršanas: 0x55ebcadf4000
Pēc pēdējā bloka atbrīvošanas: 0x55ebcadf4000
Pēc a piešķiršanas jauns18kB: 0x55ebcadf4000
brk ar strace izvade būs šāda:
brk(NULL) = 0x5608595b6000
brk (0x5608595d7000) = 0x5608595d7000
Kā jūs redzat, 0x21000 ir pievienota datu lauka beigu adresei. To var saprast no vērtības 0x5608595d7000. Tātad aptuveni 0x21000, jeb 132KB atmiņa tika piešķirta.
Šeit ir jāņem vērā divi svarīgi punkti. Pirmais ir vairāk nekā parauga kodā norādītās summas piešķiršana. Cits ir tas, kura koda rinda izraisīja brk izsaukumu, kas nodrošināja piešķiršanu.
Adreses telpas izkārtojuma nejaušība: ASLR
Palaižot iepriekš minēto lietojumprogrammas piemēru vienu pēc otras, katru reizi redzēsit dažādas adreses vērtības. Adreses telpas nejauša maiņa šādā veidā ievērojami sarežģī darbu drošības uzbrukumiem un palielina programmatūras drošību.
Tomēr 32 bitu arhitektūrā parasti tiek izmantoti astoņi biti, lai nejauši izvēlētos adrešu telpu. Bitu skaita palielināšana nebūs piemērota, jo atlikušo bitu adreses apgabals būs ļoti mazs. Arī tikai 8 bitu kombināciju izmantošana uzbrucējam darbu pietiekami neapgrūtina.
Savukārt 64 bitu arhitektūrās, tā kā ASLR darbībai var atvēlēt pārāk daudz bitu, tiek nodrošināta daudz lielāka nejaušība un palielinās drošības pakāpe.
Arī Linux kodols nodrošina spēku Android ierīces un ASLR funkcija ir pilnībā aktivizēta operētājsistēmā Android 4.0.3 un jaunākā versijā. Pat šī iemesla dēļ nebūtu nepareizi teikt, ka 64 bitu viedtālrunis nodrošina ievērojamas drošības priekšrocības salīdzinājumā ar 32 bitu versijām.
Īslaicīgi atspējojot ASLR funkciju ar šādu komandu, parādīsies, ka iepriekšējā testa lietojumprogramma atgriež tās pašas adreses vērtības katru reizi, kad tā tiek palaista:
atbalss0 | sudo tee /proc/sys/kernel/randomize_va_space
Lai to atjaunotu iepriekšējā stāvoklī, tajā pašā failā pietiks ierakstīt 2, nevis 0.
Otrais sistēmas izsaukums: mmap
mmap ir otrais sistēmas izsaukums, ko izmanto atmiņas piešķiršanai operētājsistēmā Linux. Izmantojot mmap zvanu, brīvā vieta jebkurā atmiņas apgabalā tiek kartēta ar zvanīšanas procesa adreses telpu.
Ja vēlaties atgriezt otro 16 KB nodalījumu ar funkciju free() iepriekšējā brk piemērā, veicot atmiņas piešķiršanu šādā veidā, nav mehānisma, kas novērstu šo darbību. Attiecīgais atmiņas segments tiek noņemts no procesa adrešu telpas. Tas tiek atzīmēts kā vairs neizmantots un atgriezts sistēmā.
Tā kā atmiņas piešķiršana ar mmap ir ļoti lēna, salīdzinot ar tām, kurām ir brk, ir nepieciešama brk piešķiršana.
Izmantojot mmap, jebkura brīvā atmiņas apgabals tiek kartēts uz procesa adrešu telpu, tāpēc piešķirtās vietas saturs tiek atiestatīts pirms šī procesa pabeigšanas. Ja atiestatīšana netika veikta šādā veidā, datiem, kas pieder procesam, kas iepriekš izmantoja attiecīgo atmiņas apgabalu, varēja piekļūt arī nākamais nesaistītais process. Tas padarītu neiespējamu runāt par drošību sistēmās.
Atmiņas piešķiršanas nozīme operētājsistēmā Linux
Atmiņas piešķiršana ir ļoti svarīga, jo īpaši optimizācijas un drošības jautājumos. Kā redzams iepriekš minētajos piemēros, šīs problēmas pilnīga neizpratne var nozīmēt sistēmas drošības iznīcināšanu.
Pat tādi jēdzieni, kas ir līdzīgi push un pop, kas pastāv daudzās programmēšanas valodās, ir balstīti uz atmiņas piešķiršanas operācijām. Spēja labi izmantot un pārvaldīt sistēmas atmiņu ir ļoti svarīga gan iegultās sistēmas programmēšanai, gan drošas un optimizētas sistēmas arhitektūras izstrādē.
Ja arī vēlaties iesaistīties Linux kodola izstrādē, vispirms apsveriet iespēju apgūt C programmēšanas valodu.
Īss ievads C programmēšanas valodā
Lasiet Tālāk
Saistītās tēmas
- Linux
- Datora atmiņa
- Linux kodols
Par autoru
Inženieris un programmatūras izstrādātājs, kurš ir matemātikas un tehnoloģiju cienītājs. Viņam vienmēr ir patikuši datori, matemātika un fizika. Viņš ir izstrādājis spēļu dzinēju projektus, kā arī mašīnmācīšanos, mākslīgos neironu tīklus un lineārās algebras bibliotēkas. Turklāt turpina strādāt pie mašīnmācības un lineārām matricām.
Abonējiet mūsu biļetenu
Pievienojieties mūsu informatīvajam izdevumam, lai saņemtu tehniskos padomus, pārskatus, bezmaksas e-grāmatas un ekskluzīvus piedāvājumus!
Noklikšķiniet šeit, lai abonētu