$ <b>fdformat /dev/fd0</b> /* Форматировать гибкий диск */
Double -sided, 80 tracks, 18 sec/track. Total capacity 1440 kB.
Formatting ... done
Verifying ... done
$ <b>/sbin/mke2fs /dev/fd0</b> /* Создать файловую систему Linux */
/* ...множество вывода опущено... */
$ <b>su</b> /* Стать root, чтобы использовать mount */
Password: /* Пароль не отображается */
# <b>mount -t ext2 -о mand /dev/fd0 /mnt/floppy</b> /* Смонтировать гибкий
диск, с возможностью блокировок */
# <b>suspend</b> /* Приостановить оболочку root */
[1]+ Stopped su
$ <b>ch14-lockall /mnt/floppy/x &</b> /* Фоновая программа */
[2] 23311 /* содержит блокировку */
$ <b>ls -l /mnt/floppy/x</b> /* Посмотреть файл */
-rw-r-Sr-- 1 arnold devel 13 Apr 6 14:23 /mnt/floppy/x
$ <b>echo something > /mnt/floppy/x</b> /* Попытаться изменить файл */
bash2: /mnt/floppy/x: Resource temporarily unavailable
/* Возвращается ошибка */
$ <b>kill %2</b> /* Завершить программу с блокировкой */
$ /* Нажать ENTER */
[2]- Terminated ch14-lockall /mnt/floppy/x /* Программа завершена */
$ <b>echo something > /mnt/floppy/x</b> /* Новая попытка изменения работает */
$ <b>fg</b> /* Вернуться в оболочку root */
su
# <b>umount /mnt/floppy</b> /* Демонтировать гибкий диск */
# <b>exit</b> /* Работа с оболочкой root закончена */
$
Пока выполняется
ch14-lockall
, она владеет блокировкой. Поскольку это обязательная блокировка, перенаправления ввода/вывода оболочки завершаются неудачей. После завершения
ch14-lockall
блокировки освобождаются, и перенаправление ввода/вывода достигает цели. Как упоминалось ранее, под GNU/Linux даже
root
не может аннулировать обязательную блокировку файла.
Немного отклоняясь в сторону, гибкие диски представляют отличный испытательный стенд для изучения того, как использовать инструменты, работающие с файловыми системами. Если вы сделаете что-то, что разрушит данные на гибком диске, это вряд ли будет катастрофическим, тогда как экспериментирование с действующими разделами на обычных жестких дисках значительно более рискованно.
14.3. Более точное время
Системный вызов
time()
и тип
time_t
представляют время в секундах в формате отсчета с начала Эпохи.
Разрешения в одну секунду на самом деле недостаточно, сегодняшние машины быстры, и часто бывает полезно различать временные интервалы в долях секунды. Начиная с 4.2 BSD, Berkley Unix представил ряд системных вызовов, которые сделали возможным получение и использование времени в долях секунд. Эти вызовы доступны на всех современных системах Unix, включая GNU/Linux.
14.3.1. Время в микросекундах:
gettimeofday()
Первой задачей является получение времени дня:
#include <sys/time.h>
int gettimeofday(struct timeval *tv, void *tz); /* определение POSIX, а не GLIBC */
gettimeofday()
позволяет получить время дня.
[156] В случае успеха возвращается 0, при ошибке -1. Аргументы следующие:
struct timeval *tv
Этот аргумент является указателем на
struct timeval
, которая вскоре будет описана и в которую система помещает текущее время.
void *tz
Это аргумент больше не используется; он имеет тип
void*
, поэтому он всегда должен равняться
NULL
. (Справочная страница описывает, для чего он использовался, а затем утверждает, что он устарел. Прочтите, если интересуетесь подробностями.)
Время представлено структурой
struct timeval
:
struct timeval {
long tv_sec; /* секунды */
long tv_usec; /* микросекунды */
};
Значение
tv_sec
представляет секунды с начала Эпохи;
tv_usec
является числом микросекунд в секунде.
Справочная страница GNU/Linux gettimeofday(2) документирует также следующие макросы:
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define timercmp(tvp, uvp, cmp) \
((tvp)->tv_sec cmp (uvp)->tv_sec || \
(tvp)->tv_sec == (uvp)->tv_sec && \
(tvp)->tv_usec cmp (uvp)->tv_usec)
#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
Эти макросы работают со значениями
struct timeval*
; то есть указателями на структуры, и их использование должно быть очевидным из их названий и кода. Особенно интересен макрос
timercmp()
: третьим аргументом является оператор сравнения для указания вида сравнения. Например, рассмотрим определение того, является ли одна
struct timeval
меньше другой:
struct timeval t1, t2;
...
if (timercmp(&t1, & t2, <))
/* t1 меньше, чем t2 */
Макрос развертывается в
((&t1)->tv_sec < (&t2)->tv_sec || \
(&t1)->tv_sec == (&t2)->tv_sec && \
(&t1)->tv_usec < (&t2)->tv_usec)