Мобильное программирование приложений реального времени в стандарте POSIX



Пример 5.10


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа реализует некоторые функции систем управления базами*/ /* данных в памяти, следуя принципу неуничтожения информации */ /* (изменения записываются не в сам объет, а в его новую версию) */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <signal.h> #include <sys/stat.h> #include s<ys/mman.h> #include <assert.h>

/* Размер страницы */ static int pgsz;

/* Структура для получения */ /* информации об исходном файле*/ static struct stat sbuf_src;

/* Адрес отображенного в память исходного файла*/ static char *saddr;

/* Признак того, что выполнялась функция */ /* обработки сигнала SIGSEGV */ static char sigsegv_catching;

/* * * * * * * * * * * * * * * * * * * * */ /* Функция обработки сигнала SIGSEGV. */ /* Предполагается, что этот сигнал */ /* генерируется при попытке записи в */ /* страницы, доступные только на чтение. */ /* Функция добавляет разрешение на запись*/ /* * * * * * * * * * * * * * * * * * * * */ static void sigsegv_sigaction (int sig, siginfo_t *sig_info, void *addr) { void *page_addr; /* Адрес страницы, в которую*/ /*пытались писать*/

page_addr = (char *) sig_info->si_addr - (off_t) ((char *) sig_info->si_addr - saddr) % pgsz; assert (mprotect (page_addr, pgsz, PROT_READ | PROT_WRITE) == 0); sigsegv_catching = 1; }

/* * * * * * * * * * * * * * * * * * * * * * * */ /* Установка способа обработки сигнала SIGSEGV */ /* * * * * * * * * * * * * * * * * * * * * * * */ static int sigsegv_set_proc (void (*sigsegv_actn) (int, siginfo_t *, void *), struct sigaction *old_sigsegv_sact) { struct sigaction sact;

(void) sigemptyset (&sact.sa_mask); sact.sa_flags = SA_SIGINFO; sact.sa_sigaction = sigsegv_actn; if (sigaction (SIGSEGV, &sact, old_sigsegv_sact) != 0) { perror ("SIGACTION"); return (-1); }

return 0; }

/* * * * * * * * * * * * * * * * * * * * * */ /* Функция начала работы с исходным файлом.*/ /* Нормальный результат равен нулю */ /* * * * * * * * * * * * * * * * * * * * * */ static int init_src (char *name_src) { int fd_src; /* Дескриптор исходного файла */

/* Откроем исходный файл и отобразим его в память */ if ((fd_src = open (name_src, O_RDONLY)) < 0) { perror ("OPEN-SRC"); return (-1); } if (fstat (fd_src, &sbuf_src) != 0) { perror ("FSTAT"); return (-1); } if ((saddr = (char *) mmap (NULL, sbuf_src.st_size, PROT_READ, MAP_PRIVATE, fd_src, 0)) == MAP_FAILED) { perror ("MMAP"); return (-1); }

return 0; } /* * * * * * * * * * * * * * * * * * */ /* Опрос конфигурационных параметров */ /* * * * * * * * * * * * * * * * * * */ static int init_conf_params (void) { if ((pgsz = sysconf (_SC_PAGESIZE)) == -1) { perror ("SYSCONF"); return (-1); }

return 0; }

/* * * * * * * * * * * */ /* Общая инициализация */ /* * * * * * * * * * * */ static int init_all (char *name_src) { if ((init_src (name_src) != 0) || (sigsegv_set_proc (sigsegv_sigaction, (struct sigaction *) NULL) != 0) || (init_conf_params () != 0)) { return (-1); }

return 0; }

/* * * * * * * * * * * * * * * * * */ /* Запись в файл измененных страниц*/ /* * * * * * * * * * * * * * * * * */ static int write_dlt (char *name_dlt) { int fd_dlt; /* Дескриптор файла изменений*/ volatile char tmp; /* Значение пробного байта*/ off_t pos;/* Позиция в отображенной памяти*/

if ((fd_dlt = open (name_dlt, O_CREAT | O_WRONLY | O_TRUNC, 0777)) < 0) { perror ("OPEN-DLT"); return (-1); }

/* Измененные страницы выявим путем пробных записей. */ for (pos = 0; pos < sbuf_src.st_size; pos += pgsz) { tmp = saddr [pos]; sigsegv_catching = 0; saddr [pos] = tmp; if (sigsegv_catching == 0) { /* В страницу удалось записать */ /* без генерации сигнала SIGSEGV.*/ /* Значит, она была доступна на запись.*/ /* Следовательно, ее модифицировали.*/ /* Запишем ее в файл изменений */ (void) lseek (fd_dlt, pos, SEEK_SET); assert (write (fd_dlt, saddr + pos, pgsz) == pgsz); } /* Уберем добавленное разрешение на запись */ assert (mprotect (saddr + pos, pgsz, PROT_READ) == 0); } /* for */

return (close (fd_dlt)); }

/* * * * * * * * * * * * * */ /* Функция main() вызывает */ /* описанные выше функции */ /* и обращается на запись */ /* к отображенной памяти */ /* * * * * * * * * * * * * */ int main (int argc, char *argv []) { if (argc != 3) { fprintf (stderr, "Использование: %s исходный_файл " "файл_изменений\n", argv [0]); return (-1); }

if (init_all (argv [1]) != 0) { fprintf (stderr, "Ошибка инициализации\n"); return (-1); }

printf ("Размер страницы: %d\n" "Адрес отображенного в память исходного файла: %p\n" "Длина отображенного в память исходного файла: %ld\n", pgsz, saddr, sbuf_src.st_size);

saddr [0] = '*';

return (write_dlt (argv [2])); }

Листинг 5.10. Пример программы, использующей файлы, отображенные в память.

Закрыть окно






Содержание  Назад  Вперед