Пример

Пример

На первый взгляд, использование обязательной блокировки должно решить проблему с несотрудничающими процессами, поскольку все операции чтения и записи будут приостановлены до снятия блокировки. К сожалению, проблемы с одновременными обращениями к ресурсу являются гораздо более сложными, чем кажется, что мы можем легко продемонстрировать.

Чтобы использовать в нашем примере обязательную блокировку, изменим биты разрешений файла seqno. Кроме того, мы будем использовать новую версию функции main, которая принимает количество проходов цикла for в качестве аргумента командной строки (вместо использования константы 20) и не вызывает printf при каждом проходе цикла:

solaris % cat > seqno    инициализируем файл единицей

1

^D                      конец файла

solaris % ls –l seqno

-rw-r--r-- 1 rstevens other1 2 Oct 7 11:24 seqno

solaris % chmod +l seqno включение обязательной блокировки

solaris % ls -l seqno

-rq-r-lr-- 1 rstevens other1 2 Oct 7 11:24 seqno

Теперь запустим две программы в качестве фоновых процессов: loopfcntl использует блокировку записей fcntl, а loopnone не использует блокировку вовсе. 

Укажем в командной строке аргумента 10000 — количество последовательных увеличений порядкового номера.

solaris % loopfcntl 10000 & loopnone 10000 & запуск фоновых процессов

solaris % wait                                   ожидание их завершения

solaris % cat seqno                             вывод последовательного номера

14378                                            ошибка, должно быть 20001

Рис. 9.1. Временная диаграмма работы программ loopfcntl и loopnone

Каждый раз при выполнении этих программ результат будет между 14000 и 16000. Если бы блокировка работала так как надо, он всегда был бы равен 20001. Чтобы понять, где же возникает ошибка, нарисуем временную диaгрaммy выполнения процессов, изображенную на рис. 9.1. 

Предположим, что loopfcntl запускается первой и выполняет первые восемь действий, изображенных на рисунке. Затем ядро передает управление другому процессу в тот момент, когда установлена блокировка на файл с порядковым номером. Запускается процесс loopnone, но он блокируется в первом вызове read, потому что на файл, который он пытается читать, установлена обязательная блокировка. Затем ядро передает управление первому процессу, который выполняет шаги 13-15. Пока все работает именно так, как мы предполагали, — ядро защищает файл от чтения несотрудничающим процессом, когда этот файл заблокирован.

Дальше ядро передает управление программе loopnone, которая выполняет шаги 17-23. Вызовы read и write разрешены, поскольку файл был разблокирован на шаге 15. Проблема возникает в тот момент, когда программа считывает значение 5 на шаге 23, а ядро в этот момент передает управление другому процессу. Он устанавливает блокировку и также считывает значение 5. Затем он дважды увеличивает это значение (получается 7), и управление передается loopnone на шаге 36. Однако эта программа записывает в файл значение 6. Так и возникает ошибка.

На этом примере мы видим, что обязательная блокировка предотвращает доступ к заблокированному файлу (шаг 11), но это не решает проблему. Проблема заключается в том, что левый процесс (на рисунке) может обновить содержимое файла (шаги 25-34) в тот момент, когда процесс справа также находится в состоянии обновления данных (шаги 23, 36 и 37). Если файл обновляется несколькими процессами, все они должны сотрудничать, используя некоторую форму блокировки. Один неподчиняющийся процесс может все разрушить.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Пример

Из книги Обработка событий в С++ автора Клюев Александр

Пример В примере создаются два класса обработчик и инициатор события, устанавливается связь между ними и иллюстрируется обработка события в нескольких объектах одновременно:#include "stdafx.h" #include "sigslot.h"struct EventRaiser { // источник события signal<const char*> event; // const char* – тип аргумента.


25.5. Пример

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

25.5. Пример Для закрепления материала этой главы ниже приводится пример приложения, в котором задействовано большинство функциональных возможностей qdbm. Подразумевается, что в результате выполнения этого приложения будет создана простая база данных телефонных номеров,


27.1.1. Пример

Из книги Искусство программирования на языке сценариев командной оболочки автора Купер Мендель

27.1.1. Пример В главе 8 был представлен пример использования обычной разделяемой библиотеки. Библиотеку libhello.so, которую нам удалось создать, можно загружать во время выполнения. Программа loadhello загружает libhello.so динамически и вызывает функцию print_hello, которая находится в


Пример 10-27. Простой пример сравнения строк

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

Пример 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. Пример форматирования списка файлов в каталоге

Из книги UNIX: разработка сетевых приложений автора Стивенс Уильям Ричард

Пример 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

Из книги UNIX — универсальная среда программирования автора Пайк Роб

Пример 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.# (Вы можете


9.4. Пример

Из книги автора

9.4. Пример В архитектуре x86 есть инструкции, определяющие позицию старшего и младшего значащих битов в слове. Процессор выполняет эти инструкции очень быстро. С другой стороны, чтобы сделать то же самое на языке С, потребуется написать цикл с операциями побитового


Пример

Из книги автора

Пример В листинге 11.1[1] показана простая программа, вызывающая функцию gethostbyname для любого числа аргументов командной строки и выводящая всю возвращаемую информацию.Листинг 11.1. Вызов функции и вывод возвращаемой информации//names/hostent.c 1 #include "unp.h" 2 int 3 main(int argc, char **argv) 4 { 5  char


Пример

Из книги автора

Пример Сначала приведем пример с Ipv4:freebsd % traceroute www.unpbook.comtraceroute to www.unpbook.com (206.168.112.219): 30 hops max. 24 data bytes1 12.106.32.1 (12.106.32.1) 0.799 ms 0.719 ms 0.540 ms2 12.124.47.113 (12.124.47.113) 1.758 ms 1.760 ms 1.839 ms3 gbr2-p27.sffca.ip.att.net (12.123.195.38) 2.744 ms 2.575 ms 2.648 ms4 tbr2-p012701.sffca.ip.att.net (12.122.11.85) 3.770 ms 3.689 ms 3.848 ms5 gbr3-p50.dvmco.ip.att.net (12.122.2.66) 26.202 ms 26.242 ms


Пример

Из книги автора

Пример Сначала мы запустим нашу программу с аргументом командной строки -0 и убедимся, что сервер имен отвечает на приходящие дейтаграммы, не содержащие контрольной суммы. Мы также задаем флаг -v.macosx # udpcksum -i en1 -0 -v bridget.rudoff.com domaindevice = en1local net = 172.24.37.64. netmask = 255.255.255.224cmd = udp and src host