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

Описание функций асинхронного чтения


#include <aio.h> int aio_read (struct aiocb *aiocbp); int aio_write (struct aiocb *aiocbp);
Листинг 7.1. Описание функций асинхронного чтения и записи.
Закрыть окно




#include <aio.h> int lio_listio ( int mode, struct aiocb *restrict const listio [restrict], int nent, struct sigevent *restrict sigev);
Листинг 7.2. Описание функции lio_listio().
Закрыть окно




#include <aio.h>
ssize_t aio_return ( struct aiocb *aiocbp);
int aio_error ( const struct aiocb *aiocbp);
Листинг 7.3. Описание функций aio_return() и aio_error().
Закрыть окно






#include <aio.h> int aio_cancel ( int fildes, struct aiocb *aiocbp);
Листинг 7.4. Описание функции aio_cancel().
Закрыть окно




#include <aio.h> int aio_suspend ( const struct aiocb *const listio [], int nent, const struct timespec *timeout);
Листинг 7.5. Описание функции aio_suspend().
Закрыть окно




#include <unistd.h> void sync (void);
#include <unistd.h> int fsync (int fildes);
#include <unistd.h> int fdatasync (int fildes);
#include <aio.h> int aio_fsync ( int op, struct aiocb *aiocbp);
Листинг 7.6. Описание функций синхронизации оперативной и долговременной памяти.
Закрыть окно




/* * * * * * * * * * * * * * * * * * */ /* Программа подсчитывает суммарное */ /* число строк – в файлах аргументах */ /* командной строки. */ /* Если аргументы отсутствуют или в */ /* качестве имени задан минус, */ /* читается стандартный ввод. */ /* * * * * * * * * * * * * * * * * * */
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <signal.h> #include <string.h> #include <aio.h> #include <assert.h> #include <errno.h>
int main (int argc, char *argv []) { /* Указатель на массив */ /* указателей на управляющие */ /* блоки запросов операций */ /* асинхронного чтения */ struct aiocb **lio_ptr; // Общее число строк в файлах long nlines = 0; // Признак повторного указания // стандартного ввода int dup_stdin = 0; int i;
/* Сведем случай с отсутствием */ /* аргументов к общему, */ /* воспользовавшись одним из */ /* немногих стандартизованных */ /* файлов */ if (argc == 1) { argv [0] = "-"; } else { argv [0] = "/dev/null"; }
/* Зарезервируем память, */ /* откроем заданные файлы */ /* и сформируем начальный список */ /* запросов на чтение */ assert ((lio_ptr = (struct aiocb **) malloc (sizeof (struct aiocb *) * argc)) != NULL);
for (i = 0; i < argc; i++) { assert ((lio_ptr [i] = (struct aiocb *) malloc (sizeof (struct aiocb))) != NULL);
if (strcmp (argv [i], "-") == 0) { if (dup_stdin == 0) { lio_ptr [i]->aio_fildes = STDIN_FILENO; dup_stdin = 1; } else { lio_ptr [i]->aio_fildes = fcntl (STDIN_FILENO, F_DUPFD, 0); } } else if ((lio_ptr [i]->aio_fildes = open (argv [i], O_RDONLY)) == -1) { perror ("OPEN"); free (lio_ptr [i]); lio_ptr [i] = NULL; continue; }
lio_ptr [i]->aio_offset = 0; assert ((lio_ptr [i]->aio_buf = malloc(BUFSIZ)) != NULL); lio_ptr [i]->aio_nbytes = BUFSIZ; lio_ptr [i]->aio_reqprio = 0; lio_ptr [i]->aio_sigevent.sigev_notify = SIGEV_NONE; lio_ptr [i]->aio_lio_opcode = LIO_READ; } /* for (i < argc) */
/* Поехали ... */ assert (lio_listio (LIO_NOWAIT, lio_ptr, argc, &lio_ptr [0]->aio_sigevent) == 0);
/* Будем ждать завершения */ /* операций ввода/вывода, */ /* обрабатывать прочитанные */ /* данные и */ /* инициировать новые запросы */ /* на чтение */ while (aio_suspend (( const struct aiocb **) lio_ptr, argc, NULL) == 0) { /* Выясним, какой запрос */ /* и как выполнен */
/* Число недочитанных файлов */ int nreqs = 0;
for (i = 0; i < argc; i++) { if (lio_ptr [i] == NULL) { continue; }
/* Есть обслуживаемые */ /* запросы */ nreqs++;
if (aio_error (lio_ptr [i]) == EINPROGRESS) { continue; } { // Запрос выполнен
// Число прочитанных байт ssize_t nb;
if ((nb = aio_return (lio_ptr [i])) <= 0) { /* Дошли до конца файла*/ /* или чтение */ /* завершилось ошибкой */ (void) close(lio_ptr [i]->aio_fildes); free ((void *) lio_ptr [i]->aio_buf); free (lio_ptr [i]); lio_ptr [i] = NULL; nreqs--; } else { /* Обработаем прочитанные */ /* данные */
/* Текущее начало поиска */ /* перевода строки */ char *p; /* Позиция, где нашли */ /* перевод строки */ char *p1; p = (char *) lio_ptr [i]->aio_buf; while ((p1 = (char *) memchr (p, '\n', nb - (p – (char *) lio_ptr [i]->aio_buf))) != NULL) { nlines++; p = p1 + 1; }
/* Инициируем новый */ /* запрос на чтение */ lio_ptr [i]->aio_offset += nb; (void) aio_read (lio_ptr [i]); } } } /* for (i < argc) */
/* Остались недочитанные */ /* файлы? */ if (nreqs == 0) { break; } } /* while */
printf ("%ld\n", nlines);
return 0; }
Листинг 7.7. Пример программы, использующей функции асинхронного ввода/вывода.
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа подсчитывает суммарное число строк */ /* в файлах – аргументах командной строки. */ /* Если аргументы отсутствуют или в качестве имени */ /* задан минус, читается стандартный ввод. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <signal.h> #include <string.h> #include <aio.h> #include <pthread.h> #include <assert.h>
/* Указатель на массив указателей на управляющие */ /* блоки запросов операций асинхронного чтения */ static struct aiocb **lio_ptr;
/* Общее число строк в файлах */ static long nlines_total = 0;
/* Переменная условия, на которой ждут */ /* окончания обработки всех файлов */ static pthread_cond_t open_files_cond = PTHREAD_COND_INITIALIZER;
/* Мьютекс, охраняющий доступ */ /* к переменной условия и nlines_total */ static pthread_mutex_t nlines_mutex = PTHREAD_MUTEX_INITIALIZER;
/* * * * * * * * * * * * * * */ /* Функция, вызываемая */ /* при завершении операции */ /* асинхронного ввода/вывода */ /* * * * * * * * * * * * * * */ static void end_of_aio_op (union sigval sg_vl) { int no; /* Номер выполненного запроса */ /* в общем списке */ ssize_t nb; /* Число прочитанных байт */ long nlines = 0; /* Число строк в одной */ /* прочитанной порции */ no = sg_vl.sival_int;
if ((nb = aio_return (lio_ptr [no])) <= 0) { /* Дошли до конца файла */ /* или чтение завершилось ошибкой */ (void) close (lio_ptr [no]->aio_fildes); free ((void *) lio_ptr [no]->aio_buf); free (lio_ptr [no]); lio_ptr [no] = NULL; (void) pthread_cond_signal (&open_files_cond); } else { /* Обработаем прочитанные данные */ char *p; /* Текущее начало поиска перевода строки */ char *p1; /* Позиция, где нашли перевод строки */
p = (char *) lio_ptr [no]->aio_buf; while ((p1 = (char *) memchr (p, '\n', nb - (p – (char *) lio_ptr [no]->aio_buf))) != NULL) { nlines++; p = p1 + 1; }
/* Прибавим локальную сумму к общей */ (void) pthread_mutex_lock (&nlines_mutex); nlines_total += nlines; (void) pthread_mutex_unlock (&nlines_mutex);
/* Инициируем новый запрос на чтение */ lio_ptr [no]->aio_offset += nb; (void) aio_read (lio_ptr [no]); } }
/* * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Функция проверяет, сколько осталось открытых файлов */ /* * * * * * * * * * * * * * * * * * * * * * * * * * */ static int n_open_files (int nfiles) { int nof = 0; /* Число открытых файлов */ int i;
for (i = 0; i < nfiles; i++) { if (lio_ptr [i] != NULL) { nof++; } }
return (nof); }
/* * * * * * * * * * * * * * * * * * * * */ /* Обработка аргументов командной строки, */ /* инициация начальных запросов на чтение, */ /* ожидание завершения обработки файлов, */ /* вывод результатов */ /* * * * * * * * * * * * * * * * * * * * */ int main (int argc, char *argv []) { int dup_stdin = 0; /* Признак повторного указания */ /* стандартного ввода */ int i;
/* Сведем случай с отсутствием аргументов к общему, */ /* воспользовавшись одним из немногих */ /* стандартизованных файлов */ if (argc == 1) { argv [0] = "-"; } else { argv [0] = "/dev/null"; }
/* Зарезервируем память, откроем заданные файлы */ /* и инициируем начальные запросы на чтение */ assert ((lio_ptr = (struct aiocb **) malloc (sizeof (struct aiocb *) * argc)) != NULL);
for (i = 0; i < argc; i++) { assert ((lio_ptr [i] = (struct aiocb *) malloc (sizeof (struct aiocb))) != NULL);
if (strcmp (argv [i], "-") == 0) { if (dup_stdin == 0) { lio_ptr [i]->aio_fildes = STDIN_FILENO; dup_stdin = 1; } else { lio_ptr [i]->aio_fildes = fcntl (STDIN_FILENO, F_DUPFD, 0); } } else if ((lio_ptr [i]->aio_fildes = open (argv [i], O_RDONLY)) == -1) { perror ("OPEN"); free (lio_ptr [i]); lio_ptr [i] = NULL; continue; }
lio_ptr [i]->aio_offset = 0; assert ((lio_ptr [i]->aio_buf = malloc (BUFSIZ)) != NULL); lio_ptr [i]->aio_nbytes = BUFSIZ; lio_ptr [i]->aio_reqprio = 0;
lio_ptr [i]->aio_sigevent.sigev_notify = SIGEV_THREAD; lio_ptr [i]->aio_sigevent.sigev_signo = SIGRTMIN; lio_ptr [i]->aio_sigevent.sigev_value.sival_int = i; lio_ptr [i]->aio_sigevent.sigev_notify_function = end_of_aio_op; lio_ptr [i]->aio_sigevent.sigev_notify_attributes = NULL;
/* Запрос готов, можно отправлять его на выполнение */ (void) aio_read (lio_ptr [i]); } /* for (i < argc) */
/* Дождемся завершения обработки всех указанных */ /* в командной строке файлов */ while (n_open_files (argc) > 0) { (void) pthread_cond_wait (&open_files_cond, &nlines_mutex); }
printf ("%ld\n", nlines_total);
return 0; }
Листинг 7.8. Модифицированный вариант программы, использующей функции асинхронного ввода/вывода.
Закрыть окно




#include <fcntl.h> int posix_fadvise ( int fd, off_t offset, size_t len, int advice);
#include <fcntl.h> int posix_fallocate (int fd, off_t offset, size_t len);
#include <sys/mman.h> int posix_madvise (void *addr, size_t len, int advice);
#include <stdlib.h> int posix_memalign (void **memptr, size_t alignment, size_t size);
Листинг 7.9. Описание функций рекомендательных интерфейсов.
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа подсчитывает сумму байт в файле – */ /* аргументе командной строки, */ /* пытаясь оптимизировать чтение данных с помощью */ /* функций */ /* рекомендательных интерфейсов */ /* * * * * * * * * * * * * * * * * * * * * * * * * * */
#define _XOPEN_SOURCE 600
#include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <errno.h>
int main (int argc, char *argv []) { int fd; /* Дескриптор файла-аргумента */ long sum = 0; /* Сумма байт в файле */ char *pbuf; /* Указатель на буфер обмена */ ssize_t nb; /* Число прочитанных байт */ int i;
if (argc != 2) { fprintf (stderr, "Использование: %s имя_файла\n", argv [0]); return (1); }
/* Откроем заданный файл на чтение */ if ((fd = open (argv [1], O_RDONLY)) == -1) { perror ("OPEN"); return (2); }
/* Опишем дисциплину работы с файлом */
if (((errno = posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL)) != 0) || ((errno = posix_fadvise (fd, 0, 0, POSIX_FADV_NOREUSE)) != 0)) { perror ("POSIX_FADVISE"); }
/* Зарезервируем память под буфер обмена, */ /* следуя рекомендациям */ /* на выравнивание и размер. */ /* Предполагается, что значение BUFSIZ */ /* кратно всем нужным величинам. */ if ((errno = posix_memalign ((void **) &pbuf, BUFSIZ, BUFSIZ)) != 0) { perror ("POSIX_MEMALIGN"); return (errno); }
/* Прочитаем файл и обработаем содержащиеся в нем данные */ while ((nb = read (fd, pbuf, BUFSIZ)) > 0) { for (i = 0; i < nb; i++) { sum += pbuf [i]; } }
printf ("%ld\n", sum);
free (pbuf); return (close (fd)); }
Листинг 7.10. Пример программы, использующей функции рекомендательных интерфейсов.
Закрыть окно



Содержание раздела