Блокування одночасного запису в файл без використання функції flock, Perl, Програмування, статті

Андрій Чорний

При роботі CGI-скриптів, які здійснюють запис у файли (а це більшість їх видів – лічильники. гостьові книги, форуми і т.п.) можлива ситуація, коли два або більше одночасно запущених “екземпляра” скрипта спробують одночасно записувати свої дані у файл.

Як мінімум, це загрожує втратою результатів роботи одного з примірників скрипта, а як максимум – порушенням структури файлу даних і неможливістю нормальної роботи скрипта до втручання адміна.

Тому в CGI-скриптах приймають спеціальні заходи з блокування одночасного використання файлів даних кількома скриптами одночасно. У мові Perl, як і в багатьох мовах програмування, є спеціальна функція “блокування” файлу flock.

Однак на практиці ця функція не працює в портах Perl під Windows 9x. Відповідно, скрипти, які використовують цю функцію, на мій погляд, не можуть вважатися крос-платформеними. Це також ускладнює налагодження скриптів на машині під Windows перед перноса їх на UNIX-хостинг.

Тим не менш, захист файлів від одночасного використання можна організувати і “своїм шляхом”, і це буде працювати на всіх системах.

Пропонований тут метод заснований на використанні тимчасового файлу із заздалегідь відомим ім’ям.

Суть методу проста – перед тим, як “зайняти” файл даних, скрипт створює цей тимчасовий файл, а після звільнення – видаляє. Таким чином, наявність цього тимчасового файлу означає, що файл даних зайнятий. Інший екземпляр скрипта перед записом перевіряє наявність тимчасового файлу і, якщо він є, чекає його видалення першим примірником, і тільки потім починає роботу з файлом даних.

Ім’я для тимчасового файлу може бути будь-яким – головне, щоб для блокування різних файлів даних різними скриптами використовувалися різні імена.

Фрагмент Perl-коду, який реалізує такий захист, може бути таким:

 $ Lockfile = “data.tmp”; # Ім’я тимчасового файлу блокування $ Count = 50; $ interval = 0.05; # Кількість спроб і інтервал між ними
if (-e $lockfile)
{ # Якщо тимчасовий файл є, чекаємо його видалення іншим процесом
while (($count>0)&&(-e $lockfile))
{
sleep $interval;
$count-=1;
};
};
if ($count==0){ # Тут розміщується код обробки непередбаченої помилки
}; open TF, “> $ lockfile”; # Створюємо тимчасовий файл
close TF;
#… # Тут розміщується власне код роботи з файлом даних
#…
unlink $ lockfile; # Видаляємо тимчасовий файл

Ця ділянка скрипта перевіряє, чи існує тимчасовий файл. Якщо він існує, то виробляється ($ count) перевірок його існування через інтервали ($ interval) секунд (Значення 50 і 0.05 можна замінити своїми; передбачається, що час ($ Count * $ interval) більш ніж достатня, щоб інший процес завершив роботу з файлом даних). Як тільки тимчасовий файл буде видалений іншим процесом, відбудеться вихід з циклу; далі скрипт створює свій тимчасовий файл, осущетсвлять роботу з файлом даних і видаляє тимчасовий файл.

Якщо скрипт працює на запис з кількома файлами даних, то для захисту кожного повинен бути, природно, свій вищеописаний фрагмент коду (в потрібному місці) і своє ім’я для тимчасового файлу.

У багатьох випадках має сенс “блокувати” файл даних не тільки під час запису в нього, а під час всього циклу “Читання-модифікація-запис”. В іншому випадку дуже можлива втрата результатів роботи одного з “екземплярів” скрипта.

На мій погляд, цей підхід не менш надійний, ніж “Стандартний Perl-івський”, але зате нормально працює і під Win9x, і під UNIX-подібними системами. При розробці своїх CGI-скриптів я віддаю перевагу цей метод. Зокрема, в моєму “Скрипти для ведення логів та обліку відвідувань “описаним вище чином блокується одночасне використання трьох використовуваних скриптом файлів даних, і в процесі багаторічного використання мною цього CGI-скрипта жодних ексцесів, пов’язаних саме з цим, не було.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*