Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
методичка ПО ОСРВ заочники.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
8.72 Mб
Скачать

2.9.2. Выход из системы: Как это происходит

Давайте обратимся к простому примеру. Программа, которая удаляет ваше имя из журна-I ла, должна выполнять следующие действия:

1. Открыть файл utmp.

2. Читать файл utmp до обнаружения записи о вашем терминале..

3. Сместить модифицированную запись utmp на ее место.

4. Закрыть файл utmp.

Рассмотрим эти четыре шага, один за другим.

Шаг 1: Открытие файла utmp

Программа выхода читает из файла utmp (она способна найти запись о вашем терминале), [' а также производит запись в файл utmp (чтобы заменить запись). Поэтому программа вы­хода должна открыть файл utmp на чтение и запись:

fd = open(UTMP.FILE, O.RDWR);

Шаг 2: Поиск записи о вашем терминале

Все происходит просто. В цикле while будут по одной читаться utmp записи (или будет использовано буферирование), будет производиться сравнение значения utjine с именем вашего терминала. Это может происходить так:

while(read(fd, rec, utmplen) == utmplen) /* получить следующую запись*/

if (strcmp(rec.utjne, myline) == 0) /* это моя линия? */

revise_entry(); /* удалить мое имя */

ШагЗ: Запись модифицированной записи на место

Программа выхода модифицирует запись и помещает эту запись обратно в файл. Программа изменяет значение USER_PROCESS, которое находится в utjype, на значение DEAD_PROCESS. В некоторых версиях программ выхода может производиться очистка поля с входным именем пользователя и поля с именем хост-машины, а значение, которое было в поле utjime заменяется на время выхода. Описанные действия легко запрограммировать.

Теперь возникает такой большой вопрос: как же мы запишем модифицированную запись [ обратно в файл? Если просто вызвать системный вызов write, то произойдет модификация [ счедующей записи. Это произойдет потому, что ядро поддерживает понятие текущей по­зиции в файле и смещает текущую позицию после каждого прочтения некого числа байтов или при записи в файл. При организации поиска utmp записи о нашем терминале текущая позиция была выставлена на следующую запись. Тогда возникает важный вопрос.

Вопрос: Как программа может изменить текущий указатель чтения-записи в файле?

Ответ: С помощью системного вызова lseek. Мы рассмотрим lseek в следующем разделе.

Шаг 4: Закрытие файла

Следует вызвать close(fd).

2.9.3. Смещение текущего указателя: Iseek

Unix управляет текугцим указателем в каждом открытом файле, как это показано на ри­сунке 2.8.

Каждый раз, когда вы читаете байты из файла, ядро будет читать данные с текущей пози­ции и затем смещать текущий указатель на то число байтов, которое было прочитано. Ука­затель используется и при записи данных в файл. Каждый раз, когда вы производите запись байтов в файл, ядро помещает их в файл, начиная с текущей позиции, а затем корректирует значение текущей позиции - увеличивает ее на число записанных байтов.

Рисунок 2.8

Каждый открытый файл имеет текущий указатель

Текущий указатель позиции привязан к соединению с файлом, а не к самому файлу. На­пример, если две программы открыли один и тот же файл, то после открытия для каждого соединения будет поддерживаться собственный указатель позиции. Программы могут чи­тать или записывать в разных местах файла. Системный вызов Iseek дает вам возможность изменять текущую позицию в открытом файле и имеет такие характеристики:

Iseek

НАЗНАЧЕНИЕ

Устанавливает файловый указатель с определенным сме­щением в файле

INCLUDE

#inciude < sys/types. h > #include < unustd.h >

ИСПОЛЬЗОВАНИЕ

offj oldpos = Iseekfint fd, offj dist, int base)

АРГУМЕНТЫ

fd - дескриптор файла

dist: смещение в байтах base:

base:

SE£K_SET => от начала файла

SEEK_CUR => от текущей позиции

SEEK_END => от конца файла

КОДЫ ВОЗВРАТА

-1 - при ошибке

Или предшествующая позиция в файле

Iseek устанавливает текущий указатель через дескриптор открытого файла fd в то место в файле, которое задается парой значений - dist и base. Значением base (база) можно зада­вать начало файла (0), текущую позицию в файле (1) или конец файла (2). Смещение - это число байтов относительно базы.

Например, при таком обращении к системному вызову:

Iseekffd, -(sizeof(struct utmp)), SEEK_CUR);

произойдет смещение текущего указателя на sizeof(struct utmp) байтов относительно теку­щей позиции. При обращении вида:

iseekffd, 10 * sizeof(struct utmp), SEEK_SET);

текущий указатель будет установлен на начало одиннадцатой utmp записи в файле. А при обращении вида:

Iseekffd, 0, SEEK_END); writeffd, "hello", strienf'hello"));

текущий указатель будет установлен в конец файла и там будет записана текстовая строка. Наконец, нотация вида: Iseek(fd, О, SEEK_CUR) означает возврат в текущую позицию.