Linux программирование в примерах
Помимо флагов
,O_RDONLYиO_WRONLY, при вызовеO_RDWRмогут добавляться с использованием поразрядногоopen()дополнительные флаги. Стандарт POSIX предоставляет ряд этих дополнительных флагов. В табл. 4.7 представлены флаги, которые используются для большинства обычных приложений.ORТаблица 4.7. Дополнительные флаги POSIX для
open()
Флаг Значение O_APPENDПринудительно осуществляет все записи в конец файла O_CREATСоздает новый файл, если он не существует. O_EXCLПри использовании вместе с возвращает ошибку, если файл уже существуетO_CREATO_TRUNCУрезает файл (устанавливает его длину в 0), если он существует. Если даны
иO_APPEND, можно представить, как оболочка могла бы открывать или создавать файлы, соответствующие операторамO_TRUNCи>. Например:>>int fd;extern char *filename;mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; /* 0666 */fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, mode); /* для > */fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, mode); /* для >> */Обратите внимание, что флаг
здесь не используется, поскольку как дляO_EXCL, так и для>не является ошибкой существование файла. Запомните также, что система применяет к запрошенным правам доступа>>.umaskТакже легко видеть, что, по крайней мере концептуально,
можно было бы легко написать следующим образом:creat()int creat(const char *path, mode_t mode) {return open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);}ЗАМЕЧАНИЕ. Если файл открыт с флагом
, все данные будут записаны в конец файла, даже если текущее смещение было восстановлено с помощьюO_APPEND.lseek()Современные системы предоставляют дополнительные флаги с более специализированным назначением. Они кратко описаны в табл. 4.8.
Таблица 4.8. Дополнительные расширенные флаги POSIX для
open()
Флаг Значение O_APPENDПринудительно осуществляет все записи в конец файла O_CREATСоздает новый файл, если он не существует. O_EXCLПри использовании вместе с возвращает ошибку, если файл уже существуетO_CREATO_TRUNCУрезает файл (устанавливает его длину в 0), если он существует. Флаги
,O_DSYNCиO_RSYNCтребуют некоторых пояснений. Системы Unix (включая Linux) содержат внутренний кэш дисковых блоков, который называется буферным кэшем (buffer cache). Когда возвращается системный вызовO_SYNC, данные, переданные операционной системе, были скопированы в буфер в буферном кэше. Они необязательно были записаны на диск.write()Буферный кэш значительно повышает производительность: поскольку дисковый ввод/ вывод часто на порядок и медленнее операций центрального процессора и памяти, программы значительно снизили бы производительность, если бы им пришлось ждать завершения каждой записи на диск. Вдобавок, если данные были недавно записаны на диск, при последующем чтении тех же данных они уже находились бы в буферном кэше, откуда их можно вернуть немедленно, не дожидаясь завершения операции чтения с диска.
Системы Unix осуществляют также опережающее чтение; поскольку чтение в большинстве случаев последовательное, операционная система после прочтения одного блока осуществляет чтение нескольких дополнительных последовательных блоков таким образом, что эта информация будет уже находиться в кэше, когда программа ее запросит. Если один и тот же файл читают несколько программ, они все получают преимущество, поскольку все получают свои данные из одной копии дисковых блоков файла в буферном кэше.
Все это кэширование, конечно, замечательно, но бесплатного обеда не бывает. В то время, пока данные находятся в буферном кэше и до того, как они будут записаны на диск, есть небольшое, но вполне реальное окно, в котором может случиться катастрофа; например, если выключат питание. Современные дисковые приводы обостряют эту проблему: у многих из них есть собственные внутренние буферы, поэтому при записи данных на диск они могут оказаться не записанными на носитель при выключении питания! Это может быть значительной проблемой для небольших систем, которые не находятся в информационном центре с контролируемым энергоснабжением или не имеют источников бесперебойного питания (UPS). [50]
Для большинства приложений вероятность того, что данные в буферном кэше могут быть нечаянно потеряны, довольно низка. Однако, для некоторых приложений любой такой шанс неприемлем. Поэтому в системе Unix было введено понятие синхронного ввода/вывода, при котором программе гарантируется, что по возвращении из системного вызова данные безопасно записаны на физическое устройство хранения.
Флаг
гарантирует целостность данных; данные и любая другая информация, которую операционная система должна найти, записываются на диск до возвращенияO_DSYNC. Однако, вспомогательные данные, такие, как время модификации или доступа к файлу, могут быть не записаны на диск. Флагwrite()требует, чтобы эти данные также были записаны на диск до возвращенияO_SYNC. (Здесь тоже нет бесплатного обеда; синхронные записи могут серьезно повлиять на производительность программы, заметно ее снизив.)write()