Почему аргумент brk (void * end_data_segment) не округляется до границы следующей страницы? - PullRequest
1 голос
/ 14 января 2020

С Интерфейс программирования Linux :

int brk(void * end_data_segment );

Системный вызов brk() устанавливает разрыв программы в месте, указанном end_data_segment. Поскольку виртуальная память выделяется в единицах страниц, end_data_segment эффективно округляется до границы следующей страницы.

Итак, для этой демонстрации:

#include <stdio.h>
#include <unistd.h>


int
main(int argc, char *argv[])
{
    long int page_size = sysconf(_SC_PAGESIZE);
    printf("My page size: %ld\n", page_size);
    void* c1 = sbrk(0);
    printf("program break address: %p\n", c1);
    printf("sizeof char: %lu\n", sizeof(char));
    c1 = (void*) ((char*) c1 + 1);
    printf("c1: %p\n", c1);
    brk(c1);
    void* c2 = sbrk(0);
    printf("program break address: %p\n", c2); 

}

вывод:

My page size: 4096
program break address: 0x55b0bc104000
sizeof char: 1
c1: 0x55b0bc104001
program break address: 0x55b0bc104001

Я ожидаю, что новый адрес разрыва программы будет: 0x55b0bc104000 + 0x1000(4096 in HEX) == 0x55b0bc105000

Почему я не получил 0x55b0bc105000, а 0x55b0bc104001 вместо этого?

1 Ответ

1 голос
/ 14 января 2020

Думайте об этом как о 2 возможностях:

  • выравнивание end_data_segment по границе страницы; и убедитесь, что размер базовой области виртуального адресного пространства точно соответствует значению end_data_segment

  • , не выравнивайте end_data_segment по границе страницы; и убедитесь, что размер базовой области виртуального адресного пространства выровнен (округлен) до размера страницы

Для первой возможности - портативное программное обеспечение (которое не имеет представления о том, что размер страницы) может (например) увеличить end_data_segment на 1/8 части страницы и сделать это 8 раз, и вместо того, чтобы в итоге получить одну дополнительную страницу (результат, который вы, естественно, ожидаете), он в конечном итоге с 8 дополнительными страницами (на 7 страниц больше, чем хотелось, и на 7 страниц больше, чем ожидалось). Хуже; программное обеспечение может уменьшить размер end_data_segment менее чем на страницу, и ничего не будет делать (будет округлено до первоначального значения); и это также может быть сделано много раз, приводя к большой области, от которой программное обеспечение пыталось избавиться, но все еще существует. Конечно, их можно комбинировать - программное обеспечение может увеличить end_data_segment на 1 байт, а затем уменьшить end_data_segment на один байт в середине всего oop, вызывая неожиданную утечку памяти (пространства), которая может быстро поглотить все доступные виртуальные адресное пространство, когда люди ожидали, что это ничего не пропустит. Конечно, программное обеспечение может явно обойти все проблемы, добавляя (нестандартные / непереносимые) исправления везде, но это будет ужасно уродливо.

Вторая возможность (не выравнивать end_data_segment) является более интуитивным, более удобным и менее подверженным ошибкам.

...