Анимация
JavaScript
|
Главная Библионтека Чтение и запись файлов с блокировкой А теперь настало время продемонстрировать работу функции ata() и writedataO, выполняющих блокировку текстовой базы даннгх. Для этого нам нужно определить имя файла-семафора и добавить в код вызовы функций getjock() и release lock]), описанных в пред]дущем разделе. Код этих функций мы поместили в начало листинга 15.4. Линг 15.4. Пример выполнения операций чтения и записи тековой базы д1х с блокировкой 1 bin/perl 2: use strict; 3: изг Fcntl qw(:flock); 5: w $seiiiaphore file=-/tmp/listl54.Bem-; 7: I Функщи дон бтккрсЕки (сщ1еет раз&13ккрсЕ(ш бесаоЕчю дсп 8: 811b get nock { 9: open(SEM, ">$эагщЬаге £11е") 10: die "Ск хи соЕдрЕ1;(и сем:р: $1"; 11: flock(SEM, LOCK EX) 11 die "Оийка ipi бшкирсаие: $!"; 12: } 13: 14: 15 16: адЬ геДваэе 1оск { close(S£H); 17: } 18: 19: sub readdata { 20: open(PH, "phone.txt") dig "Ошибка ipzE сощьши айга phciE.txt: $!"; 21: my{*DATA)=<PH>; 22: сЬотр(вОАТА); 23: close(PH); 24: return (i DATA); 25: } 26: sub writedata { 27: my(eDATA)=e ; 28: open(PH, ">boe.txt") \\ dig "СПкбка ipi сощьши айга jirie.txt: $1"; 29: foreach (gDATA) { 30: print PH "$ \n"; 31: } 32: close(PH); t A та1Ж СЕихвет бшкирав! 33: > 34: шу iPHOHEL; 35: 36: get lock(); 37: gPHOKEL=readdata(); 38: push(gPHONEL, "ЕЮкгвй 555-1012"); 39: writedata{ gPBOHEL); 40: release lock{); :"pf Большая часть кода из листинга 15.4 вам уже должна быть хорошо знакома. ШАШШ функции getJock{), releaseJock(), readdata() и writedataf) бьши онисаны выше на этом занятии. . Основная часть программы начинается со строки 34. Сначала выполняется блокировка файла с помощью функции get lock(). Затем с помощью функции readdata() содержимое файла базы данных помещается в массив выполняется добавле- ние новой записи и содержимое массива записывается обратно в файл базы данных с помощью функции writedata(). После того как будут выполнены все операции, блокировка снимается с помощью функции release lock(}. В результате другие программы смогут получить доступ к нашей базе данных. Блокировка вWindows 9x Как оказалось, в системах Windows 95/98 не поддерживается блокировка файлов. Почему это происходит? Причина заключается в том, что в этих операционных системах только одной программе разрешается открывать файл по записи в данный момент времени, поэтому блокировка оказывается ненужной. В результате, если выполнить функцию flock в системе Windows 9x, будет выдано следующее сообщение об ошибке: ПоскО uniniplemetited on this platform at line... (Функция flock{) не реализована на этой платформе...) К сказанному выше остается добавить, что операционная система Windows 9x является однопользовательской. в этой книге в листингах примеров, связанных с блокировкой, используются функции get lock() и release lock(). Использование этих функций в системах Windows 95 и 98 вызывает появление сообщения об ошибке, поскольку, как уже было сказано выше, в этих операционных системах функция flock не реализована. Поэтому, чтобы примеры работали без ошибок, просто закомментируйте вызовы функций get iock() и release lock(), Для напоминания в текст листингов будут включены соответствующие комментарии. Блокировка в системах UNIX и Windows NT В некоторых случаях требуется, чтобы несколько программ одновременно могли читать и записывать данные в файл, однако при этом функция flock по каким-либо причинам оказывается недоступной. И даже на тех платформах, где функция flock реализована, бывают ситуации, когда ею нельзя воспользоваться. Например, в системах UNIX эта функция не работает в сетевой файловой системе (NFS). Кроме- того, часто программы запускаются в смешанной среде с выделенным сервером на базе UNIX и рабочими станциями на базе Windows. При этом функция flock поддерживается в системах UNIX и не поддерживается в системах Windows. За более подробной информацией о блокировке файлов и функции flock обратитесь к разделу 5, "Files and Formats", сниска часто задаваемых вопросов по Perl. Для этого откройте раздел perlfaq5 электронной документации по Perl. Резюме На этом занятии было рассмотрено несколько методов долговременного хранения данных. Сначала мы изучили файлы DBM и способы их привязки к хэшам в программах на Perl, а затем рассмотрели способы использования текстовых файлов для создания простейших баз данных. И в конце занятия бгла описана проблема одновременного доступа к файлам нескольких программ. Вы узнали, как с помощью блокировок разрешать конфликты доступа к данным и сохранять целостность базы данных. Вопросы и ответы Можно ли сохранять структуры данных, описанные на 13-м занятии, "Структуры и ссылки", в DBM-файле или текстом файле? Если ответить с ходу, то нет, хотя в принципе это возможно, но довольно сложно. Для начала нужно преобразовать "структуру" в строку, которая будет представлять данные и саму структуру, их содержащую. После этого полученную строку нужно использовать как значение ключа в хэше, связанном с DBM-файлом. В Peri предусмотрен специальный модуль, который все это делает автоматически. Его имя - Data::Dumper. Как можно заблокировать DBM-файл? DBM-файлы блокируются с помощью системы семафоров, которая была описана на этом занятии. Вам нужно использовать функции get loc)c() и release lock(), описанные в листинге 15.3. Поместите эти функции перед открытием DBM-файла и после его закрытия, как показано в следующем примере: get 1оск(); dbmopenl%hash, "foo", 0644) [J die "dmboperv: $!"; Shash{newkey}="3Ha4eBBe"; dbmclose(*hash); release lock(}; Можно каким-нибудь образом проверить, приведет ли вызов функции flock к паузе в работе программы без реальной приостановки выполнения программы? Да, это возможно. У функции flock предусмотрено специальное значение параметра, использование которого не приводит к приостановке выполнения программы. Такой вызов функции flock называется неблокирующим. Чтобы проверить, вызовет ли функция flock приостановку в выполнении программы, поместите значение lOCK NB после типа блокировки, как показано use Fcntl qw(:flock); t Попытка вьшолнять монопольный захват без перевода t программы в состояние ожццания if (not flock(LF, L0CK EXL0CK NB)) { print "Нельзя вьшолнить блокировку: $1"; Более того, вы даже можете перевести программу на некоторое время в состояние ожидания, а затем вывести соответствующее сообщение, если в конечном итоге не удастся выполнить блокировку через заданное число попыток. Вот пример: use Fcntl qw(:flock); $lock atteBpts=3i while (no K EX1.0CK NB)) { sl€£p 5; t sgM 5 СЕни $lock attempts~; "пьая вьпслнипь блскироЕ!" if (ret $attertpts) ; 15-с.Обраб дах в Perl 247 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 [ 76 ] 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |