Программирование для Linux. Профессиональный подход
Шрифт:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
static int alloc_size;
static char* memory;
void segv_handler(int signal_number) {
printf("memory accessed!\n");
mprotect(memory, alloc_size, PROT_READ | PROT_WRITE);
}
int main {
int fd;
struct sigaction sa;
/*
Назначение функции segv_handler обработчиком сигнала
SIGSEGV. */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = &segv_handler;
sigaction(SIGSEGV, &sa, NULL);
/* Выделение одной страницы путем отображения в памяти файла
/dev/zero. Сначала память доступна только для записи. */
alloc_size = getpagesize;
fd = open("/dev/zero", O_RDONLY);
memory =
mmap(NULL, alloc_size, PROT_WRITE, MAP_PRIVATE, fd, 0);
close(fd);
/* Запись на страницу для получения ее копии в частное
использование. */
memory[0] = 0;
/* Запрет на запись в память. */
mprotect(memory, alloc_size, PROT_NONE);
/* Попытка записи в память. */
memory[0] = 1;
/* Удаление памяти. */
printf("all done\n");
munmap(memory, alloc_size);
return 0;
}
Программа работает по следующей схеме.
1. Задается обработчик сигнала
SIGSEGV
. 2. Файл
/dev/zero
отображается в памяти, из которой выделяется одна страница. В эту страницу записывается инициализирующее значение, благодаря чему программе предоставляется частная копия страницы. 3. Программа защищает память, вызывая функцию
mprotect
с флагом PROT_NONE
. 4. Когда программа впоследствии обращается к памяти, Linux посылает ей сигнал
SIGSEGV
, который обрабатывается в функции segv_handler
. Обработчик сигнала отменяет защиту памяти, разрешая выполнить операцию записи. 5. Программа удаляет область память с помощью функции
munmap
. 8.10. Функция nanosleep: высокоточная пауза
Функция
nanosleep
является более точной
sleep
, принимая указатель на структуру типа timespec
, где время задается с точностью до наносекунды, а не секунды. Правда, особенности работы ОС Linux таковы, что реальная точность оказывается равной 10 мс, но это все равно выше, чем в функции sleep
. Функцию nanosleep
можно использовать в приложениях, где требуется запускать различные операции с короткими интервалами между ними. В структуре
timespec
имеются два поля: ■
tv_sес
— целое число секунд; ■
tv_nsec
— дополнительное число миллисекунд (должно быть меньше, чем 109). Работа функции
nanosleep
, как и функции sleep
, прерывается при получении сигнала. При этом функция возвращает значение -1, а в переменную errno записывается код EINTR
. Но у функции nanosleep
есть важное преимущество. Она принимает дополнительный аргумент — еще один указатель на структуру timespec
, в которую (если указатель не равен NULL
) заносится величина оставшегося интервала времени (т.е. разница между запрашиваемым и прошедшим промежутками времени). Благодаря этому можно легко возобновлять прерванные операции ожидания. В листинге 8.8 показана альтернативная реализация функции
sleep
. В отличие от стандартного системного вызова эта функция может принимать дробное число секунд и возобновлять операцию ожидания в случае прерывания по сигналу. Листинг 8.8. (better_sleep.c) Высокоточная реализация функции
sleep
#include <errno.h>
#include <time.h>
int better_sleep(double sleep_time) {
struct timespec tv;
/* Заполнение структуры timespec на основании указанного числа
секунд. */
tv.tv_sec = (time_t)sleep_time;
/* добавление неучтенных выше наносекунд. */
tv.tv_nsec = (long)((sleep_time - tv.tv_sec) * 1e+9);
while (1) {
/* Пауза, длительность которой указана в переменной tv.
В случае прерывания по сигналу величина оставшегося
промежутка времени заносится обратно в переменную tv. */
int rval = nanosleep(&tv, &tv);
if (rval == 0)
/* пауза успешно окончена. */
return 0;
else if (errno == EINTR)
/* Прерывание по сигналу. Повторная попытка. */
continue;
else
/* Какая-то другая ошибка. */
return rval;
Поделиться:
Популярные книги
Опыты
Научно-образовательная:
философия
7.43
рейтинг книги
Добыча. Всемирная история борьбы за нефть, деньги и власть
Документальная литература:
публицистика
5.00
рейтинг книги
Дважды одаренный. Том VI
6. Дважды одаренный
Фантастика:
аниме
альтернативная история
фэнтези
фантастика: прочее
5.50
рейтинг книги
Воины
Фантастика:
фэнтези
7.00
рейтинг книги
Вечера в древности
Проза:
классическая проза
историческая проза
5.00
рейтинг книги
Годы странствий
Документальная литература:
биографии и мемуары
6.25
рейтинг книги
Цикл романов "Целитель". Компиляция. Книги 1-17
Целитель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
12
5.00
рейтинг книги
Путь Шедара
4. Другая сторона
Фантастика:
боевая фантастика
6.83
рейтинг книги
Месть Седьмой
5. Наследие Лориена
Фантастика:
фэнтези
9.05
рейтинг книги
Солнечная система (Астрономия и астрофизика)
Научно-образовательная:
прочая научная литература
астрономия и космос
5.00
рейтинг книги
Газлайтер. Том 19
19. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
6.25
рейтинг книги
Законы Рода. Том 5
5. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Техники ландшафтной арт-терапии
Научно-образовательная:
психотерапия и консультирование
5.00