Linux: Ochrona pamięci i płaska pamięć

0

Takie pytanie do specjalistów od Linux. Skoro Linux używa płaskiego modelu pamięci, bez segmentacji to:

int main()
{
    char tab[1] = {'a'};
    tab[10000] = 'b';
}

nie powinno wywalać błędu, bo przeciez nie wychodzimy z segmentu danych, ani nic podobnego. Kernel powinien dostać błąd stronicowania i zaalokować pamięć pod tym adresem.

Jaki mechanizm wykrywa, ze proces coś namieszał?Mi przychodzi do głowy tylko albo:

  • wyjście poza limit dostępny dla pojedynczego procesu sprawdzany przy "page fault"
  • chęć dostępu do pamięci zbytnio oddalonej liniowo od pozostałej reszty danych

Jakieś sugestie?

0

Pamiętaj o tym że są inne procesy, program nie dostaje całej pamięci do dyspozycji, zaś tylko tyle co potrzebuje.
Kawałek pamięci na dane, kawałek na stos, kawałek na kod, no i ewentualnie kawałek na heap.
Jeżeli wyłazisz poza te fragmenty to masz błąd.

0

Masz rację... Przemyślałem to sobie i teraz widze jak głupio myślałem...

Po prostu Linux przeciez pamięta, jakie ramki oddał do dyspozycji procesowi, a błąd wynikający z powyższego kodu nie jest błędem segmentacji tylko błędem stronicowania. pÓÓÓÓki poruszamy się w obrębie jednej ramki (zazwyczaj 4kB) to nic się nie dzieje, a jak wyjdziemy poza ramkę to mamy błąd stronicowania, dlatego:

char tab[1] = {'a'};
tab[2000] = 'b';
//nie daje błędu, bo jesteśmy ciągle w tej samej ramce
char tab[1] = {'a'};
tab[4000] = 'b';
//daje czasami błąd, bo raz sąsiednia ramka jest przydzielona, a raz nie
char tab[1] = {'a'};
tab[6000] = 'b';
//tak jak powyżej, ale częściej, bo częsciej już tak daleko nie ma przydzielonej ramki
char tab[1] = {'a'};
tab[9000] = 'b';
//prawie zawsze błąd po prawie zawsze już poza przydzielonymi ramkami
char tab[1] = {'a'};
tab[13000] = 'b';
//zawsze błąd, bo nie ma przydzielonych ramek tak daleko w liniowym adresowaniu

--
Opolski Portal Programstyczny
http://programowanie.opole.pl

0

Każdy proces ma własną niezależną przestrzeń adresową. Wszystkie nieobsłużone wyjątki (przesyłane jako sygnały) spowodują zamknięcie programu. Szczerze mówiąc to nie pamiętam jak zrealizowano mechanikę stosu w Linuksie, może tak jak Windows od dłuższego czasu, doalokowuje strony po wyjściu poza jego zakres, ale w wypadku sterty nie ma prawa tak robić. Program nie ma prawa tak sobie próbować używać dowolnych adresów, jedynie przydzielone przez system.

0

Właściwie nie rozumiem poco rozważać kiedy błędny fragment kodu spowoduje wywalenie się programu a kiedy nie. Wystarczy założyć że tak czy owak, wcześniej czy później, może dopiero po kolejnych rozwinięciach programu, może nie bezpośrednio (zmieni jakąś inną zmienną) a i tak ten kod spowoduje wywalenie się programu.

0

A takie rozważania mogą się przydać po to, że jak jakiś kod się wysypuje z segmentation error to możesz przypuszczać, że modyfikujesz dane tylko do odczytu i na przykład Twój student gdzieś w kodzie robi tak:

char* ptr = "string";
$ptr = 'a';

A jak masz paging error to robi tak:

char[1] tab = {'a'};
tab[1000] = 'b';
0

I tak nie będziesz wiedział co dokładnie się posypało, dlaczego nie odpalać od razu pod kontrolą debuggera?

0

Oczywiście, że bez debuggera to się nie obejdzie na dłuższą metę, ale taka wstępna diagnoza może dać jakieś rozeznanie, w która stronę spoglądać.

0

Nic to nie da:

char msg1[]="ala ma kota";
char msg2[]="x";
msg1[12]='a';

Jaki błąd wywali?

0

Twoje jest na stosie, więc daje się modyfikować bez błędu.

    char* ptr1 = "ala ma kota";
    char* ptr2 = "x";
    ptr1[12]='a';

To jest w segmencie danych i błąd. Kompilator w takim przypisaniu, daje stringa do danych, a wskaźnik na stos. W Twoim poprzednim dane też były na stosie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1