10.4.4.1. Пример: GNU Coreutils safe_read() и safe_write()
10.4.4.1. Пример: GNU Coreutils safe_read() и safe_write()
Для обработки случая EINTR в традиционных системах GNU Coreutils использует две функции, safe_read() и safe_write(). Код несколько запутан из-за того, что один и тот же файл за счет включения #include и макросов реализует обе функции. Из файла lib/safe-read.c в дистрибутиве Coreutils:
1 /* Интерфейс read и write для .повторных запусков после прерываний.
2 Copyright (С) 1993, 1994, 1998, 2002 Free Software Foundation, Inc.
/* ... куча шаблонного материала опущена... */
56
57 #ifdef SAFE_WRITE
58 # include "safe-write.h"
59 # define safe_rw safe_write /* Создание safe_write() */
60 # define rw write /* Использование системного вызова write() */
61 #else
62 # include "safe-read.h"
63 # define safe_rw safe_read /* Создание safe_read() */
64 # define rw read /* Использование системного вызова read() */
65 # undef const
66 # define const /* пусто */
67 #endif
68
69 /* Прочесть (записать) вплоть до COUNT байтов в BUF из(в) дескриптора FD, повторно запуская вызов при
70 прерывании. Вернуть число действительно прочитанных (записанных) байтов, 0 для EOF
71 или в случае ошибки SAFE_READ_ERROR(SAFE_WRITE_ERROR). */
72 size_t
73 safe_rw(int fd, void const *buf, size_t count)
74 {
75 ssize_t result;
76
77 /* POSIX ограничивает COUNT значением SSIZE_MAX, но мы еще больше ограничиваем его, требуя,
78 чтобы COUNT <= INT_MAX, для избежания ошибки в Tru64 5.1.
79 При уменьшении COUNT сохраняйте указатель файла выровненным по размеру блока.
80 Обратите внимание, что read (write) может быть успешным в любом случае, даже если прочитано (записано)
81 менее COUNT байтов, поэтому вызывающий должен быть готов обработать
82 частичные результаты. */
83 if (count > INT_MAX)
84 count = INT_MAX & -8191;
85
86 do
87 {
88 result = rw(fd, buf, count);
89 }
90 while (result < 0 && IS_EINTR(errno));
91
92 return (size_t) result;
93 }
Строки 57–67 обрабатывают определения, создавая соответствующим образом safe_read() и safe_write() (см. ниже safe_write.c).
Строки 77–84 указывают на разновидность осложнений, возникающих при чтении. Здесь один особый вариант Unix не может обработать значения, превышающие INT_MAX, поэтому строки 83–84 выполняют сразу две операции: уменьшают значение числа, чтобы оно не превышало INT_MAX, и сохраняют его кратным 8192. Последняя операция служит эффективности дисковых операций: выполнение ввода/вывода с кратным основному размеру дискового блока объемом данных более эффективно, чем со случайными размерами данных. Как отмечено в комментарии, код сохраняет семантику read() и write(), где возвращенное число байтов может быть меньше затребованного.
Обратите внимание, что параметр count может и в самом деле быть больше INT_MAX, поскольку count представляет тип size_t, который является беззнаковым (unsigned). INT_MAX является чистым int, который на всех современных системах является знаковым.
Строки 86–90 представляют действительный цикл, повторно осуществляющий операцию, пока она завершается ошибкой EINTR. Макрос IS_EINTR() не показан, но он обрабатывает случай в системах, на которых EINTR не определен. (Должен быть по крайней мере один такой случай, иначе код не будет возиться с установкой макроса; возможно, это было сделано для эмуляции Unix или POSIX в не-Unix системе.) Вот safe_write.c:
1 /* Интерфейс write для повторного запуска после прерываний.
2 Copyright (С) 2002 Free Software Foundation, Inc.
/* ...куча шаблонного материала опущена... */
17
18 #define SAFE_WRITE
19 #include "safe-read.с"
В строке 18 #define определяет SAFE_WRITE; это связано со строками 57–60 в safe_read.с.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
27.1.1. Пример
27.1.1. Пример В главе 8 был представлен пример использования обычной разделяемой библиотеки. Библиотеку libhello.so, которую нам удалось создать, можно загружать во время выполнения. Программа loadhello загружает libhello.so динамически и вызывает функцию print_hello, которая находится в
Пример
Пример В качестве примера передачи идентифицирующих данных мы изменим наш потоковый доменный сервер Unix, так чтобы он запрашивал идентифицирующие данные клиента. В листинге 15.12 показана новая функция, read_cred, аналогичная функции read, но возвращающая также структуру fcred,
Пример
Пример В листинге 6.21 приведен текст программы, которая определяет четыре ограничения, показанные в табл. 6.2.Листинг 6.21. Определение системных ограничений для очередей сообщений System V//svmsg/limits.c1 #include "unpipc.h"2 #define MAX_DATA 64*10243 #define MAX_NMESG 40964 #define MAX_NIDS 40965 int max_mesg;6 struct mymesg
Пример
Пример Легче всего продемонстрировать проблему нашей реализации из предыдущего раздела с помощью примера. На рис. 8.1 изображена временная диаграмма выполнения нашей программы, а текст самой программы приведен в листинге 8.9. Рис. 8.1. Временная диаграмма выполнения
Пример
Пример Вернемся к нашему примеру из листинга 9.2 и перепишем функции my_lock и my_unlock из листинга 9.1 так, чтобы воспользоваться блокировкой записей Posix. Текст этих функций приведен в листинге 9.3.Листинг 9.3. Блокировка записей fcntl по стандарту Posix//lock/lockfcntl.c1 #include
Пример
Пример В качестве примера использования RPC перепишем листинги 15.1 и 15.2 для использования Sun RPC вместо дверей. Клиент вызывает процедуру сервера с аргументом типа long, а возвращаемое значение представляет собой квадрат аргумента. В листинге 16.1[1] приведен текст первого файла,
9.4. Пример
9.4. Пример В архитектуре x86 есть инструкции, определяющие позицию старшего и младшего значащих битов в слове. Процессор выполняет эти инструкции очень быстро. С другой стороны, чтобы сделать то же самое на языке С, потребуется написать цикл с операциями побитового
Пример 9-3. Еще один пример ограничения времени ожидания ввода от пользователя
Пример 9-3. Еще один пример ограничения времени ожидания ввода от пользователя #!/bin/bash# timeout.sh# Автор: Stephane Chazelas,# дополнен автором документа.INTERVAL=5 # предел времени ожиданияtimedout_read() { timeout=$1 varname=$2 old_tty_settings=`stty -g` stty -icanon min 0 time ${timeout}0 eval read $varname # или просто read $varname
Пример 10-27. Простой пример сравнения строк
Пример 10-27. Простой пример сравнения строк #!/bin/bash# match-string.sh: простое сравнение строкmatch_string (){ MATCH=0 NOMATCH=90 PARAMS=2 # Функция требует два входных аргумента. BAD_PARAMS=91 [ $# -eq $PARAMS ] || return $BAD_PARAMS case "$1" in "$2") return $MATCH;; * ) return $NOMATCH;; esac}a=oneb=twoc=threed=twomatch_string $a # неверное число
Пример 12-20. Пример форматирования списка файлов в каталоге
Пример 12-20. Пример форматирования списка файлов в каталоге #!/bin/bash# За основу сценария взят пример "man column".(printf "PERMISSIONS LINKS OWNER GROUP SIZE DATE TIME PROG-NAME " ; ls -l | sed 1d) | column -t# Команда "sed 1d" удаляет первую строку, выводимую командой ls,#+ (для локали "С" это строка: "total N",#+ где "N" -- общее
Пример 12-45. Пример работы с m4
Пример 12-45. Пример работы с m4 #!/bin/bash# m4.sh: Демонстрация некоторых возможносией макропроцессора m4# Строкиstring=abcdA01echo "len($string)" | m4 # 7echo "substr($string,4)" | m4 # A01echo "regexp($string,[0-1][0-1],&Z)" | m4 # 01Z# Арифметикаecho "incr(22)" | m4 # 23echo "eval(99 / 3)" | m4 #
Пример 24-2. Еще один пример проверки аргументов с помощью "И-списков"
Пример 24-2. Еще один пример проверки аргументов с помощью "И-списков" #!/bin/bashARGS=1 # Ожидаемое число аргументов.E_BADARGS=65 # Код завершения, если число аргументов меньше ожидаемого.test $# -ne $ARGS && echo "Порядок использования: `basename $0` $ARGS аргумент(а)(ов)" && exit $E_BADARGS# Если
Пример 25-8. Пример реализации алгоритма Решето Эратосфена
Пример 25-8. Пример реализации алгоритма Решето Эратосфена #!/bin/bash# sieve.sh# Решето Эратосфена# Очень старый алгоритм поиска простых чисел.# Этот сценарий выполняется во много раз медленнее# чем аналогичная программа на C.LOWER_LIMIT=1 # Начиная с 1.UPPER_LIMIT=1000 # До 1000.# (Вы можете
Пример
Пример В примере создаются два класса обработчик и инициатор события, устанавливается связь между ними и иллюстрируется обработка события в нескольких объектах одновременно:#include "stdafx.h" #include "sigslot.h"struct EventRaiser { // источник события signal<const char*> event; // const char* – тип аргумента.