printf("Текущий брейк-адрес= 0x%x\n", obrk);
/* Выделим 64 байта из хипа */
naddr = malloc(64);
/* Определим новый брейк-адрес */
nbrk = sbrk(0);
printf("Новый адрес области malloc= 0x%x,"
" брейк-адрес= 0х%x (увеличение на %d байтов)\n",
naddr, nbrk, nbrk — obrk);
/* "Освободим" выделенную память и проверим, что произошло
на самом деле */
free(naddr);
printf("free(0x%x)\n", naddr);
obrk = sbrk(0);
printf("Новый брейк-адрес= 0x%x (увеличение на %d байтов)\n",
obrk, obrk — nbrk);
}
Откомпилируем и запустим программу:
$ a.out
Текущий брейк-адрес= 0x20ac0
malloc(64)
Новый адрес области malloc = 0x20ac8, брейк-адрес = 0x22ac0
(увеличение на 8192 байтов)
free(0x20ac8)
Новый брейк-адрес = 0x22ac0 (увеличение на 0 байтов)
$
Как видно из вывода программы, несмотря на освобождение памяти функцией
Создание и управление процессами
Работая в командной строке shell вы, возможно, не задумывались, каким образом запускаются программы. На самом деле каждый раз порождается новый процесс, а затем загружается программа. В UNIX эти два этапа четко разделены. Соответственно система предоставляет два различных системных вызова: один для создания процесса, а другой для запуска новой программы.
Новый процесс порождается с помощью системного вызова
#include
#include
pid_t fork(void);
□ идентификаторы пользователя и группы,
□ переменные окружения,
□ диспозицию сигналов и их обработчики,
□ ограничения, накладываемые на процесс,
□ текущий и корневой каталог,
□ маску создания файлов,
□ все файловые дескрипторы, включая файловые указатели,
□ управляющий терминал.
Более того, виртуальная память дочернего процесса не отличается от образа родительского: такие же сегменты кода, данных, стека, разделяемой памяти и т.д. После возврата из вызова
Легче перечислить немногочисленные различия между этими процессами, а именно:
□ дочернему процессу присваивается уникальный идентификатор PID.
□ идентификаторы родительского процесса PPID у этих процессов различны,
□ дочерний процесс свободен от сигналов, ожидающих доставки,
□ значение, возвращаемое системным вызовом
Последнее замечание требует объяснения. Как уже говорилось, возврат из функции
В возвращаемом
main() {
int pid;
pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
/* Эта часть кода выполняется дочерним процессом */
printf("Потомок\n");
} else {
/* Эта часть кода выполняется родительским процессом */
printf("Родитель\n");
}
}
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии