Linux программирование в примерах
$ <b>ch12-mktemp</b> /* Запуск программы */Filename is /tmp/myfileQES4WA /* Вывод имени файла */$ <b>cat /tmp/myfileQES4WA</b>Here's lookin' at you, kid' /* Содержит то, что ожидалось */$ <b>ls -l /tmp/myfileQES4WA</b> /* To же с владельцем и доступом */-rw------- 1 arnold devel 28 Sep 18 09:27 /tmp/myfileQES4WA$ <b>rm /tmp/myfileQES4WA</b> /* Удалить его */$ <b>ch12-mktemp</b> / * Используется ли повторно то же имя? */Filename is /tmp/myfileic7xCy /* Нет. Это хорошо */$ <b>cat /tmp/myfileic7xCy</b> /* Снова проверить содержание */Here's lookin' at you, kid!$ <b>ls -l /tmp/myfileic7xCy</b> /* Снова проверить владельца и доступ */-rw------- 1 arnold devel 28 Sep 18 09:28 /tmp/myfileic7xCyВсе кажется работающим замечательно,
возвращает уникальное имя,mktemp()создает файл с нужными правами доступа, и содержание то самое, которое ожидалось. Так в чем же проблема со всеми этими функциями?ch12-mktempИсторически
использовала простой, предсказуемый алгоритм для создания замещающих символов для 'mktemp()' в шаблоне. Более того, интервал между временем, когда генерируется имя файла, и временем, когда создается сам файл, создает состояние гонки.ХХХХХХКак? Ну, Linux и Unix являются системами с квантованием времени, методикой, которая разделяет время процессора между всеми исполняющимися процессами. Это означает, что, хотя программа кажется выполняющейся все время, в действительности есть моменты, когда процессы спят, т.е. ожидают выполнения на процессоре.
Теперь рассмотрите программу профессора для отслеживания оценок студентов. Как профессор, так и злоумышленный студент в одно и то же время используют сильно нагруженную многопользовательскую систему. Программа профессора использует для создания временных файлов
, видевший в прошлом, как оценивающая программа создает и удаляет временные файлы, выяснил алгоритм, который используетmktemp(). (В версии GLIBC нет этой проблемы, но не все системы используют GLIBC!) Рис 12.2 иллюстрирует состояние гонки и то, как студент его использует.mktemp()Рис. 12.2. Состояние гонки с
mktemp()Вот что случилось.
1. Оценивающая программа использует
для создания имени файла. По возвращении изmktemp()открыто окно состояния гонки (строка 19 вmktemp()).ch12-.mktemp.c2. Ядро останавливает оценивающую программу, чтобы могли поработать другие программы в системе. Это происходит до вызова
.open()Пока оценивающая программа остановлена, студент создает файл с тем же самым именем, которое вернула
. (Помните, выяснить алгоритм было просто.) Студент создает файл с дополнительной ссылкой, так что когда оценивающая программа удаляет файл, он все еще будет доступен для прочтения.mktemp()3. Теперь оценивающая программа открывает файл и записывает в него данные. Студент создал файл с правами доступа
, поэтому это не представляет проблему.-rw-rw-rw-4. Когда оценивающая программа завершает работу, она удаляет временный файл. Однако, у студента все еще есть копия. Например, может быть возможность получения прибыли при заблаговременной продаже своим товарищам их оценок.
Наш пример упрощенный; помимо простого похищения данных с оценками умный (хотя и аморальный) студент мог бы вместо этого изменить данные. Если бы профессор не проверял результаты работы своей программы дважды, никто бы ничего не узнал.
ЗАМЕЧАНИЕ. Мы не рекомендуем делать что-либо из этого! Если вы студент, не пытайтесь сделать что-либо подобное. Первое и самое главное, это неэтично. Во-вторых, вас могут выгнать из школы. В-третьих, ваши профессора, наверное, не сталь наивны, чтобы использовать
в своих программах. Этот пример лишь для иллюстрации!mktemp()По приведенным и другим причинам, все три описанные в данном разделе функции не следует никогда использовать. Они существуют в POSIX и GLIBC лишь для поддержки старых программ, которые были написаны до того, как была осознана опасность этих процедур С этой целью системы GNU/Linux генерируют во время компоновки сообщение:
$ <b>cc ch12-mktemp.c -о ch12-mktemp</b> /* Компилировать программу *//tmp/cc1XCvD9.о(.text+0x35): In function 'main':: the use of 'mktemp' is dangerous, better use 'mkstemp'(Мы рассмотрим
в следующем подразделе.)mkstemp()Если бы в вашей системе не было
, подумайте, как вы могли бы использовать эти интерфейсы для ее эмулирования. (См. также «Упражнения» для главы 12 в конце.)mkstemp()12.3.2. Создание и открывание временных файлов (хорошо)
Есть две функции, не имеющие проблем состояния гонки. Одна из них предназначена для использования с библиотекой
:<stdio.h>#include <stdio.h> /* ISO С */FILE *tmpfile(void);Другая функция для использования с системными вызовами на основе дескрипторов файлов:
#include <stdio.h> /* XSI */int mkstemp(char* template);возвращает значениеtmpfile(), представляющее уникальный открытый временный файл. Файл открывается в режиме "FILE*".w+bозначает «открыть для чтения и записи, сначала урезав файл», a b означает двоичный, а не текстовый режим. (На системах GNU/Linux или Unix нет разницы, но на других системах есть.) Файл автоматически удаляется, когда закрывается указатель файла; нет способа получить имя файла, чтобы сохранить его содержимое. Программа вw+демонстрируетch12-tmpfile.c:tmpfile()/* ch12-tmpfile.с --- демонстрация tmpfile().Проверка ошибок для краткости опущена */#include <stdio.h>int main(void) {static char mesg[] =
