- •2.1. Введение
- •2.2. Вопросы, относящиеся к команде who
- •2.2.1. Программы состоят из команд
- •2.3. Вопрос 1: Что делает команда who?
- •2.3.1. Обращение к справочнику
- •2.4. Вопрос 2: Как работает команда who?
- •2.4.1. Мы теперь знаем, как работает who
- •2.5. Вопрос 3: Могу ли я написать who?
- •2.5.1. Вопрос: Как я буду читать структуры из файла?
- •2.5.2. Ответ: Использование open, read и close
- •2.5.3. Написание программы who 1.С
- •2.5.4. Отображение записей о вхождениях в систему
- •2.5.5. Написание версии who2.С
- •2.6. Проект два: Разработка программы ср (чтение и запись)
- •2.6.1. Вопрос 1: Что делает команда ср?
- •2.6.2. Вопрос 2: Как команда ср создает файл и как пишет в него? Создание/транкатенация файла
- •2.6.3. Вопрос 3: Могу ли я написать программу ср?
- •2.6.4. Программирование в Unix кажется достаточно простым
- •2.7. Увеличение эффективности файловых операций ввода/ вывода: Буферирование
- •2.7.1. Какой размер буфера следует считать лучшим?
- •2.7.2 Почему на системные вызовы требуется тратить время?
- •2.7.3. Означает ли, что наша программа who2.С неэффективна?
- •2.7.4. Добавление буферирования к программе who2.С
- •2.8. Буферизация и ядро
- •2.8.1. Если буферизация столь хороша, то почему ее не использует ядро?
- •2.9. Чтение файла и запись в файл
- •2.9.1. Выход из системы: Что происходит?
- •2.9.2. Выход из системы: Как это происходит
- •2.9.3. Смещение текущего указателя: Iseek
- •2.9.4. Кодирование выхода из системы через терминал
- •2.10. Что делать с ошибками системных вызовов?
- •3.1. Введение
- •3.2. Вопрос 1: Что делает команда is?
- •3.2.1. Команда Is выводит список имен файлов и оповещает об атрибутах файлов
- •3.2.3. Наиболее употребимые опции
- •3.2.4. Первый ответ: Итоговые замечания
- •3.3. Краткий обзор дерева файловой системы
- •3.4. Вопрос 2: Как работает команда Is?
- •3.4.1. Что же такое каталог, в конце концов?
- •3.4.2. Работают ли системные вызовы open, read и close в отношении каталогов?
- •3.4.3. Хорошо, хорошо. Но как же мне прочитать каталог?
- •3.5. Вопрос 3: Могу ли я написать Is?
- •3.5.1. Что еще нужно делать?
- •3.6. Проект 2: Написание версии Is -I
- •3.6.1. Вопрос 1: Что делает Is-I?
- •3.6.2. Вопрос 2: Какработает Is -I?
- •3.6.3. Ответ: Системный вызов stat получает информацию о файле
- •3.6.4. Какую еще информацию можно получить с помощью системного вызова stat?
- •3.6.5. Чего мы достигли?
- •3.6.6. Преобразование числового значения поля mode в символьное значение
- •3.6.7. Преобразования числового представления идентификаторов собственника/группы в строковое представление
- •3.6.8. Объединение всего вместе: Is2.C
- •3.7. Три специальных разряда
- •3.7.1. Разряд Set-User-id
- •3.7.2Разряд Set-Group-id
- •3.7.3 Разряд Sticky Bit
- •3.7.4. Специальные разряды nls-l
- •3.8. Итоги для команды is
- •3.9. Установка и модификация свойств файла
- •3.9.1. Тип файла
- •3.9.2. Разряды прав доступа и специальные разряды
- •3.9.3. Число ссылок на файл
- •3.9.4. Собственник и группа для файла
- •3.9.5. Размер файла
- •3.9.6. Время последней модификации и доступа
- •3.9.7. Имя файла
3.6.5. Чего мы достигли?
Мы достигли того, что правильно отображаются такие атрибуты, как ссылки, размер, имя Вывод значения времени модификации представлен в формате time_t. Мы можем исполн зовать ctime, чтобы конвертировать это значение в строку, где будет содержаться месяц,] день, время или год. В поле mode в нашем выводе выводится значение режима в числовой виде, а при работе Is вывод будет символьным:
-rw-rw-r--
Вывод в полях user и group представлен в числовом виде, а в команде Is в этих полях выводятся символьные имена собственника и имя группы. Для окончания работы над нашим вариантом по написанию Is -I нам необходимо еще ознакомиться, как конвертировать! числовые значения полей mode, user и group в символьные представления значений.
3.6.6. Преобразование числового значения поля mode в символьное значение
Каким образом представлены разряды, соотнесенные типу файла и правам доступа, в поле I st_mode? Как нам выбрать эти атрибуты и представить их как последовательность из I 10 символов? Какая связь между восьмеричным числом 100664 и строкой rw-rw-r-? Ответ: поле st mode шестнадцатиразрядное. Отдельные атрибуты закодированы в соответствующих подстроках в этом 16-разрядном поле. На рисунке 3.4 показано назначение пяти таких подстрок.
Рисунок 3.4
Представление кодов типа файла и прав доступа
Подстрока из первых четырех разрядов предназначена для представления типа файла. В четырехразрядном поле можно хранить 16 возможных комбинаций из 1 и 0. Каждый из этих двоичных кодов может служить для представления отдельного типа файла. В настоя-1 шее время используется семь типов файлов.
Следующая подстрока из трех разрядов предназначена для хранения специальных атрибутов файла. Каждый разряд в этой подстроке соответствует специальному атрибуту. Если любой разряд установлен в ' 1', то соответствующий ему атрибут установлен. Если разряд установлен в '0', то соответствующий ему атрибут не установлен. Эти специальные атрибуты называются set-user-ID, set-group-ID и sticky bits. Они будут рассмотрены позже. Наконец, далее расположены три последовательности трехразрядных подстрок для представления прав доступа к файлу. Первая подстрока - для хранения прав доступа собственника, вторая подстрока - для хранения прав доступа группы и последняя подстрока – для хранения прав доступа всех остальных пользователей. Для каждого класса пользователей в подстроке из трех разрядов можно задать наличие или отсутствие прав на чтение, запись и исполнение. Значение какого-либо разряда в любой из подстрок, равное “1”, означает, что соответствующий вид доступа разрешен. Значение какого-либо разряда в любой из подстрок, равное '0', означает, что соответствующий вид доступа запрещен.
Секреты кодировки подполей
Весьма распространенным приемом является упаковка специальных значений в подполя больших строк. Эта идея иллюстрируется на таких примерах:
Примеры кодирования подстрок |
|
617-495-4204 |
Область, коммутатор, линия |
027-93-1111 |
Личный социальный номер |
128.103.33.100 |
IP - адрес |
Как читать подполя: Маскирование
Как можно определить - принадлежит ли телефонный номер 212-333-4444 кодовой облас ти212? Очень просто. Вы берете три первых числа из номера и сравниваете их подстрокой 212. Другой подход будет заключаться в том, что вы обнуляете все цифры в телефонном номере, кроме первых трех, и затем сравниваете результат с 212-000-0000.
Техника обнуления указанных подполей называется маскированием. Подход напоминает о маске на лице, которая все скрывает, за исключением ваших глаз и, возможно, ушей и рта. Мы можем использовать набор масок для преобразования значения поля st_mode в символьную строку, которая выводится стандартной командой Is -I.
Кодирование подполей является общим и важным методом системного программирования. Вам будет необходимо помнить о четырех моментах для понимания кодирования I и маскирования подполей.
Первый момент: Концепция маскирования
Маскирование значения - это обнуление установленных значений разрядов в числе при | условии, что остальные разряды остаются неизменяемыми.
Второй момент: Целое число - это битовая строка
Целые числа хранятся в компьютере как последовательность двоичных разрядов. На рисунке 3.5 показано, как десятичное значение числа 215 выражается как последовательность единиц и нулей, используя двоичную нотацию (основание 2) Каково будет десятичное значение, которое соответствует двоичному значению 00011010?
Рисунок 3.5 Преобразования десятичного представления в двоичное
Третий момент: Техника маскирования
Операция поразрядного "И"(т. е. &) дает возможность маскировать одно значение с помощью другого значения. На рисунке 3.6 показано восьмеричное значение 100664 (основание 8), которое маскируется кодом, составленным пользователем. Отметьте, как некоторые единичные разряды в исходном числе будут преобразованы в 0 с помощью определенных разрядов маски.
Рисунок 3.6
Использование двоичной маски
Четвертый момент: Использование восьмеричного основания
Использование масок в двоичном формате является достаточно утомительным, особенно! для слов длиной в 16 или 32 разряда. Поэтому произведем группировку больших десятичных чисел в трехсимвольные "связки" (например, 23,234,456,022) для более простого прочтения значения числа, а также сгруппируем двоичные представления больших чисел в трехсимвольные "'связки" и преобразуем каждую "связку" в одно восьмеричное число (значение от 0 до 7).
Например, мы можем произвести группировку по связкам в двоичном числе 1000000110110100 и получить такое представление: 1,000,000,110,110,100. После чего преобразуем каждую связку и получим такое представление числа: 0100664, которое легче воспринимается.
Использование маскирования для декодирования значения типа файла
Тип файла кодируется в первом четырехразрядном поле mode. Для декодирования информации в этом поле мы можем использовать маскирование. Прежде всего, мы используем маску для обнуления всех разрядов, кроме первых четырех разрядов. Затем сравним полученный результат с кодами для каждого из типов:
Определения этих кодов находятся в заголовочном файле <sys/stat.h>:
#define |
SIFMT 0170000 |
/* тип файла 7 |
#define |
SJFREG 0100000 |
Г обычный */ |
#define |
SJFDIR 0040000 |
Г каталог */ |
«define |
SIFBLK 0060000 |
/* специальный блочный */ |
«define |
S IFCHR 0020000 |
/*специальный символьный */ |
«define |
S.IFIFO 0010000 |
Г программный канал fifo */ |
«define |
SIFLNK 0120000 |
/* символическая ссылка */ |
«define |
SIFSOCK 0140000 |
/* сокет */ |
Символьная константа S_IFMT - это маска, с помощью которой выбираются первые четыре разряда. Значением маски является число 0170000. Убедитесь в том, что эта маска выбирает правильный набор разрядов с помощью обратного преобразования каждого восьмеричного представления цифры в трехразрядный двоичный эквивалент. Код типа для обычного файла (SJFREG) равен 0100000. Значение кода типа для каталога равно 0040000.
Например, во фрагменте кода:
if ((info.st.mode & 0170000) ==0040000)
printf("this is a directory.");
будет проводиться проверка на тип каталога, что делается с помощью маскирования всех полей, кроме поля типа, и последующего сравнении результата с кодом типа каталога.
Если вы пожелаете написать код для маскирования и проверки, вы можете использовать при этом макросы из заголовочного файла <sys/stat.h>:
/*
* Макросы для типов файла
*/
#define |
S ISHFO(m) (((m)&(0170000)) == (0010000)) |
«define |
S ISDIR(m) (((m)&(0170000)) == (0040000)) |
«define |
SJSCHR(m) (((m)&(0170000)) == (0020000)) |
#define |
SJSBLK(m) (((m)&(0170000)) == (0060000)) |
«define |
SJSREG(m) (((m)&(0170000)) == (0100000)) |
С помощью этих макросов можно так написать наш код:
if(SJSDIR(info.st_mode))
printf("this is a directory.");
Использование маскирования для декодирования разрядов прав доступа
Последние девять разрядов в mode предназначены для представления прав доступа на выполнение операций чтения, записи и исполнения с файлом для каждого класса пользователей. В стандартной версии команды Is производится преобразование этих девяти двоичных разрядов, каждый из которых установлен в 1 или 0, в строку, которая состоит из последовательности символов и прочерков.
Назначение каждого разряда маски можно посмотреть в файле <sys/stat.h>. Следующая программа представляет собой простое, читабельное приложение, которое проверяет отдельно каждый разряд:
/*
* В этой функции извлекается значение mode и формируется символьный массив.
* В символьный массив помещается значение типа файла и
* девять символов для представления прав доступа.
* ЗАМЕЧАНИЕ: Коды setuid, setgid sticky
* не рассматриваются
*/
void mode to_letters(int mode, char str[])
{
strcpy(str,"-......—"); |
/* по умолчанию - отсутствие всех прав */ |
if(SJSDIR(mode))str[0] = 'd'; |
/* каталог */ |
if(SJSCHR(mode))sir[0] = 'c'; |
/* символьные устройства */ |
if(SISBLK(mode))str[0] = 'b'; |
/* блочное устройство */ |
if(mode&SJRUSR)str[1] = 'r'; |
/* 3 разряда для собственника */ |
if(mode&S_IWUSR)str[2] = 'w'; |
|
if(mode&SJXUSR)str[3] = Y; |
|
if(mode&SIRGRP)str[4] = 'r'; |
/* 3 разряда для группы */ |
if(mode&SJWGRP)str[5] = 'w,; |
|
if(mode&SJXGRP)str[6] = Y; |
|
if (mode & SJROTH) str[7] = V; |
/* 3 разряда для всех остальных */ |
if (mode& S.IWOTH) str[8] ='w'.-if (mode & S IXOTH) str[9] = V; }
if (mode& S.IWOTH) str[8] ='w';
if (mode & S IXOTH) str[9] = V;
}
Декодирование разрядов и написание версии Is
У нас накопилось достаточно знаний для написания версии команды Is, которая может правильно работать с длинным форматом вывода. Мы можем правильно выводить значения таких атрибутов файла, как размер, ссылки и имя файла. Мы имеем возможность взять значение поля mode и преобразовать его значение в стандартную последовательность из символов и прочерков. Можно преобразовать с помощью ctime значение времени из формата time_t в строковый формат. А каковы соображения по строчному представлению имен собственника и группы?
