45 argv[0], argv[1], rw_mode, strerror(errno));
46 (void)close(fd);
47 return 1;
48 }
49
50 /* заблокировать файл */
51 memset(&lock, '\0', sizeof(lock));
52 lock.l_whence = SEEK_SET;
53 lock.l_start = 0;
54 lock.l_len =0; /* блокировка всего файла */
55 lock.l_type = F_WRLCK; /* блокировка записи */
56
57 if (fcntl(fd, F_SETLK, &lock) < 0) {
58 fprintf(stderr, "%s: %s: cannot lock the file: %s\n",
59 argv[0], argv[1], strerror(errno));
60 (void)close(fd);
61 return 1;
62 }
63
64 pause();
65
66 (void)close(fd);
67
68 return 0;
69 }
Программа устанавливает права доступа и создает файл, указанный в командной строке (строки 25 и 26). Затем она записывает в файл некоторые данные (строка 34). Строка 41 добавляет к правам доступа бит setgid, а строка 43 изменяет их. (Системный вызов fchmod()
обсуждался в разделе 5.5.2 «Изменение прав доступа: chmod()
и fchmod()
».)
Строки 51–55 устанавливают struct flock
для блокировки всего файла, а затем блокировка осуществляется реально в строке 57. Выполнив блокировку, программа засыпает, используя системный вызов pause()
(см. раздел 10.7 «Сигналы для межпроцессного взаимодействия»). После этого программа закрывает дескриптор файла и завершается. Вот расшифровка с комментариями, демонстрирующая использование обязательной блокировки файлов:
$ fdformat /dev/fd0 /* Форматировать гибкий диск */
Double -sided, 80 tracks, 18 sec/track. Total capacity 1440 kB.
Formatting ... done
Verifying ... done
$ /sbin/mke2fs /dev/fd0 /* Создать файловую систему Linux */
/* ...множество вывода опущено... */
$ su /* Стать root, чтобы использовать mount */
Password: /* Пароль не отображается */
# mount -t ext2 -о mand /dev/fd0 /mnt/floppy /* Смонтировать гибкий
диск, с возможностью блокировок */
# suspend /* Приостановить оболочку root */
[1]+ Stopped su
$ ch14-lockall /mnt/floppy/x & /* Фоновая программа */
[2] 23311 /* содержит блокировку */
$ ls -l /mnt/floppy/x /* Посмотреть файл */
-rw-r-Sr-- 1 arnold devel 13 Apr 6 14:23 /mnt/floppy/x
$ echo something > /mnt/floppy/x /* Попытаться изменить файл */
bash2: /mnt/floppy/x: Resource temporarily unavailable
/* Возвращается ошибка */
$ kill %2 /* Завершить программу с блокировкой */
$ /* Нажать ENTER */
[2]- Terminated ch14-lockall /mnt/floppy/x /* Программа завершена */
$ echo something > /mnt/floppy/x /* Новая попытка изменения работает */
$ fg /* Вернуться в оболочку root */
su
# umount /mnt/floppy /* Демонтировать гибкий диск */
# exit /* Работа с оболочкой root закончена */
$
Пока выполняется ch14-lockall
, она владеет блокировкой. Поскольку это обязательная блокировка, перенаправления ввода/вывода оболочки завершаются неудачей. После завершения ch14-lockall
блокировки освобождаются, и перенаправление ввода/вывода достигает цели. Как упоминалось ранее, под GNU/Linux даже root
не может аннулировать обязательную блокировку файла.
Немного отклоняясь в сторону, гибкие диски представляют отличный испытательный стенд для изучения того, как использовать инструменты, работающие с файловыми системами. Если вы сделаете что-то, что разрушит данные на гибком диске, это вряд ли будет катастрофическим, тогда как экспериментирование с действующими разделами на обычных жестких дисках значительно более рискованно.
14.3. Более точное время