Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Захардкодить адрес указателя в Си и инициализировать значение по данному указателю

#c


Прохожу курс операционных систем и пытаюсь реализовать алгоритм страничной организации
памяти.  В алгоритме есть ограниченное количество страниц (NUMBER_PAGEBLE_PAGES = 33)
и структура mem_map_t, содержащая поле-указатель на первый элемент каждой страницы
uint32_t *page. 

Ниже приведен код, который, как предполагается, содержит локальный указатель, получающий
адрес свободной страницы, и далее, начиная с полученного адреса, выполняет последовательную
инициализацию всего адресного пространства данной страницы значением 0:

static uint32_t *allocate_page(void)

{

    uint32_t i = 0; 
    uint32_t j = 0;
    uint32_t *page = NULL;

    printf("here 2\n");
    while (i < NUM_PAGEABLE_PAGES) {
        if (m_map[i].in_use == 0) {
            m_map[i].in_use = 1;
            page = m_map[i].page;
            printf("here 3   %p\n", page);

            // Данная строка выдает segmentation fault 11 при инициализации ячейки
памяти по указанному адресу. Почему?
            *page = 0;                     

            printf("here 4   %p\n", page);

            // данный "while-loop" пытается инициализировать все остальные ячейки
в указанном
            while (j < 1024) {
                j++;
                printf("here 5\n");
                page[j] = 0;
                printf("here 6\n");
            }
            break;
        }
        i++;
    }
    return page;
}


Вывод в терминале следующий $ ./a.out
here 2
here 3   0x100000
Segmentation fault: 11


Получается, что локальный указатель uint32_t *page получает начальное значение 0x100000,
но при инициализации ячейки памяти по указанному адресу значением 0 выдает ошибку.

Может быть есть идеи в чем здесь дело?
Заранее спасибо!
    


Ответы

Ответ 1



Ошибка к обращению чужой памяти. Адрес берётся здесь: page = m_map[i].page; Отсюда возможные причины ошибки: Точно ли её там выделяется 1025? Вы ведь с индекса 1 начинаете обход массива, так как j++; стоит до обращения к памяти. Попробуйте поставить после, если так не было странно задумано. Кстати, такие числа лучше выносить в константы. Вы также не ставите значение j равным нулю перед циклом с j циклом. Это задумано? Если нет, то надо поправить.

Ответ 2



Как уже обозначалось в моем вопросе, работа ведется над курсом "Операционные системы", который предполагает разработку своей простенькой операционной системы с нуля, но в описании вопроса был упущен момент, что все (в данном конкретном случае) адресное пространство должно инициализироваться мануально (вручную), без использования стандартных Си библиотек. Конкретным заданием на данном этапе является написание алгоритма страничной организации оперативной памяти (paging). Вы были правы. В приведенном программном коде, содержащем метод "allocate_page()", выскочила ошибка при обращении к чужому адресному пространству. Вопрос заключался в том, чтобы понять причину ее возникновения, так как в приведенном выше коде вроде бы задается адрес переменной "page = m_map[i].page", что в результате означает " page = 0x100000 ", и далее, начиная с данного адреса, не выделяя заранее памяти, начинается попытка инициализации ячеек памяти каждого последующего адреса, а именно "0x100000, 0x100004, 0x100008, ... , 0x101000 (не включая последний)" значением "(uint32_t) 0". Ошибка, как оказалось, возникала из-за того, что выделение памяти с помощью библиотечных функций "malloc()" или "calloc()" в реализуемом проекте не предусматривается, а сегменты памяти, к которым в свою очередь производился запрос, оказывались занятыми другими процессами, запущенными на машине, на которой производилась компиляция кода. Реализуемый же проект предполагает наличие абсолютно пустой оперативной памяти, которая делится на сегменты (страницы) в мануальном (ручном) режиме, в определенном смысле приведенная в коде функция "allocate_page()" является неким самодельным прототипом "malloc()" ( или "calloc()" ). Поэтому в описанном в моем вопросе алгоритме после инициализации указателя " page = m_map[i].page; ", (что в результате дает page = 0x100000), при обращении к области памяти по данному адресу выдавалась ошибка сегментации, так как данная область, как написано чуть выше, уже используется либо операционной системой, либо каким-то процессом в защищенном режиме на запускаемой данный код машине, а это значит, что доступ к выбранному сегменту адресного пространства запрещен. При запуске в терминале код выдает ошибку сегментации, а в "Bochs x86-64 emulator" все сработало отлично, все инициализировалось как и предполагалось (имеется ввиду " p[0] = 0, p[1] = 0, ... , p[1023] = 0 "). Что же касается индекса "j" и началом "while-loop" с "j = 1", а не с "j = 0" это все были эксперименты, чтобы определить, где алгоритм инициализации адресов в адресном пространстве "0x10000 - 0x101000" "споткнется" и выдаст ошибку. Спасибо за дискуссию и советы, все было интересно и по делу!

Комментариев нет:

Отправить комментарий