sys_brk
include/linux/sched.h
zdefiniowana
jest struktura task_struct
, stanowiaca opis kontekstu
procesu. W sklad opisu kontekstu wchodzi rowniez informacja o
polozeniu i dostepnej pamieci procesu. Jest ona przechowywana
w polu ww. struktury o nazwie mm
typu mm_struct
(definicja rowniez w include/linux/sched.h
).
W strukturze task_struct
znajduje sie ponadto pole
rlim
typu rlimit[]
(definicja w
include/linux/resouce.h
) opisujace ograniczenia
procesu, m.in. ograniczenie na ilosc przylaczonej pamieci operacyjnej.
exec
, a takze
podczas inicjacji systemu, do pamieci operacyjnej ladowany jest kod
programu oraz rezerwowane jest miejsce na zmienne i stos procesu.
W systemie Linux mapa wirtualnej przestrzeni adresowej dzialajacego
procesu wyglada nastepujaco:
Podzial pamieci jest wyznaczny przez opis kontekstu procesu, a scislej
przez jego pole mm
(zob. Struktury).
Na samym dole
przestrzeni adresowej umieszczony jest kod wykonywalny
(zazwyczaj od adresu 0, mozna jednak skompilowac jadro tak,
zeby pierwsza strona (=4kB) przestrzeni adresowej byla wolna;
dzieki takiemu rozwiazaniu przypisania na wskaznik o wartosci
NULL powoduja zgloszenie bledu ochrony pamieci. Algorytmy
ladowania kodu programu znajduja sie w plikach
/fs/binfmt_aout.c
oraz /fs/binfmt_elf.c
).
Za segmentem kodu rozpoczyna sie segment danych.
Jego poczatkowa czesc stanowi blok danych inicjowanych
(tj. takich, dla ktorych wartosci sa wczytywane z pliku
wykonywalnego). Druga czesc to tzw. dane nieinicjowane (bss),
zerowane przed uruchomieniem procesu przez system operacyjny.
Podzial powyzszy jest wyznaczany przez pola struktury mm
:
start_code
- adres pierwszego bajtu kodu wykonywalnego
end_code
- adres pierwszego bajtu za kodem wykonywalnym
start_data
- adres pierwszego bajtu danych inicjowanych
end_data
- adres pierwszego bajtu po danych inicjowanych
brk
- adres pierwszego bajtu podanych nieinicjowanych
(wartosc break)
start_brk
- wartosc brk
w momencie
uruchomienia procesu
(na poczatku brk
=start_brk
).
brk
lub sbrk
o nastepujacej semantyce:
int brk(void *new_brk)
- ustawia nowa wartosc break,
zwraca -1 w przypadku bledu,
void *sbrk(ptrdiff_t increment)
- zmienia wartosc
break o increment
, zwracajac nowa otrzymana
wartosc.
Zadna z tych funkcji nie jest jednak prostym wywolaniem systemowej funkcji
sys_brk
(definicja w pliku mm/mmap.c
) o semantyce:
unsigned long sys_brk(unsigned long brk)
- sprobuj
zmienic wartosc break i zwroc obowiazujaca wartosc.
Jak widac, nie istnieje w systemie cos takiego, jak
algorytm sbrk. Algorytmy realizujace funkcje brk
i sbrk
mozna zrealizowac w latwy sposob np. poprzez
wywolanie sys_brk(0)
w celu sprawdzenia biezacej
wartosci break, a nastepnie ponowne wywolanie
sys_brk
z odpowiednim parametrem i przygotowanie wyniku
na podstawie porownania ze stara wartoscia break
end_code
(czyli: program chce oddac wiecej niz posiada).
rlim
w strukturze task_struct
; w systemie Linux
limit przylaczonej pamieci operacyjnej dla jednego procesu wynosi
standardowo 2GB).
brk
arch/i386/entry.S,
fs/exec.c,
fs/binfmt_aout.c,
fs/binfmt_elf.c,
include/linux/resource.h,
kernel/fork.c,
kernel/sched.c,
mm/mmap.c
struct task_struct,
struct mm_struct
exit
, ktorej wartosc (w zapisie
szestnastkowym) wynosi
deadbeef.
MAX_TASKS_PER_USER
= 256 (liczba procesow jednego uzytkownika)
MIN_TASKS_LEFT_FOR_ROOT
= 4 (liczba procesow zarezerwowanych
dla administratora),
NR_TASKS
= 512 (liczba procesow w systemie),
TASK_SIZE
= 3GB (maksymalny adres w wirtualnej przestrzeni
adresowej procesu). Oprocz tego nie nazwany parametr przechowywany
w current -> rlim
okresla maksymalna ilosc pamieci
przylaczonej do procesu na 2GB.