МИНИСТЕРСТВО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ

Московский Государственный институт электроники и математики

(Технический университет)

 

 

 

Кафедра Управление и информатика в технических системах

 

 

 

КОМАНДНЫЙ ИНТЕРПРЕТАТОР UNIX

ФАЙЛОВАЯ СИСТЕМА UNIX

 

 

 

Методические указания

к лабораторным работам № 1, 2

по курсу "Системное программное обеспечение"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Москва 2002

 

Составители:      доц., канд. техн. наук В.Э. Карпов

ст. преподаватель И.П. Карпова

 

 

 

 

 

 

 

УДК 681.3

Командный интерпретатор UNIX. Файловая система UNIX.: Метод. указания к лабораторным работам №1 и 2 по курсу "Системное программное обеспечение" / Моск. гос. ин-т электроники и математики; Сост.: В.Э. Карпов, И.П. Карпова. М., 2002. – 32 с.

 

 

 

Лабораторная работа № 1 посвящена изучению командного языка операционной системы UNIX, особое внимание уделено перенаправлению потоков ввода/вывода и программным каналам.

Лабораторная работа №2 включает сведения об организации файловой системы ОС UNIX и принципах работы с файлом как с разделяемым ресурсом. Приведены системные вызовы для работы с файлами и примеры программ.

Каждая лабораторная работа выполняется в объеме 3 часов.

Методические указания к лабораторным работам являются составной частью учебно-методического комплекса по дисциплине “Системное программное обеспечение”, изучаемой студентами специальности 21.01 “Управление и информатика в технических системах”.

 

 

 

 

 

 

 

ISBN

 

ОГЛАВЛЕНИЕ

ЛАБОРАТОРНАЯ РАБОТА №1. КОМАНДНЫЙ ИНТЕРПРЕТАТОР
1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

1.1. Общие положения
1.2. Регистрация в системе
1.3. Пользователи системы и владельцы файлов
1.4. Перенаправление потоков и программные каналы
2. КОМАНДНЫЙ ЯЗЫК СИСТЕМЫ UNIX. ИНТЕРПРЕТАТОР SHELL
2.1. Общие положения
Переменные языка shell
2.2. Справочные команды
2.3. Команды работы с каталогами
2.4. Команды работы с файлами
2.5. Команды работы с текстовыми файлами
2.6. Команды работы с процессами
3. ВЫПОЛНЕНИЕ ЛАБОРАТОРНОЙ РАБОТЫ
4. ЗАДАНИЯ НА ЛАБОРАТОРНУЮ РАБОТУ

ЛАБОРАТОРНАЯ РАБОТА №2. ФАЙЛОВАЯ СИСТЕМА UNIX
1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
1.1. Структура файловой системы
1.2. Типы файлов
1.3. Управление файлами
2. ПРОГРАММИРОВАНИЕ ОПЕРАЦИЙ ВВОДА-ВЫВОДА
3. ПРИМЕРЫ ПРОГРАММ РАБОТЫ С ФАЙЛАМИ
4. ВЫПОЛНЕНИЕ ЛАБОРАТОРНОЙ РАБОТЫ
5. ЗАДАНИЯ НА ЛАБОРАТОРНУЮ РАБОТУ
БИБЛИОГРАФИЧЕСКИЙ СПИСОК

 

ЛАБОРАТОРНАЯ РАБОТА №1. КОМАНДНЫЙ ИНТЕРПРЕТАТОР

Цель лабораторной работы – ознакомление с командным языком системы UNIX (особенно с командами работы с файловой системой), с перенаправлением потоков ввода/вывода и с программными каналами.

1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

1.1. Общие положения

UNIX – это ядро операционной системы разделения времени, то есть программа, которая распоряжается ресурсами вычислительной машины и предоставляет их пользователям. Она дает пользователям возможность запускать свои программы, управляет периферийными устройствами и обеспечивает работу файловой системы. UNIX является многозадачной многопользовательской ОС.

Работу ОС UNIX можно представить в виде функционирования множества взаимосвязанных процессов. При загрузке системы сначала запускается ядро, которое в свою очередь запускает основную задачу, порождающую все последующие процессы – процесс init (процесс № 1).

Взаимодействие пользователя с системой UNIX происходит в интерактивном режиме посредством командного языка. Оболочка операционной системы – shell – интерпретирует вводимые команды, запускает соответствующие программы (процессы), формирует и выводит ответные сообщения.

Важной составной частью UNIX является файловая система. Она имеет иерархическую структуру, образующую дерево каталогов и файлов. Корневой каталог обозначается символом "/", путь по дереву каталогов состоит из имен каталогов, разделенных символом "/", например:

/usr/include/sys

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

Каждый файл ОС UNIX может быть однозначно определен некоторой структурой данных, называемой описателем файла (дескриптором). Он содержит всю информацию о файле: тип файла, режим доступа, идентификатор владельца, размер, адрес файла, даты последнего доступа и последней модификации, дату создания и пр.

Обращение к файлу происходит по имени. Локальное имя файла представляет собой набор символов, в версии System V имеющий длину от 1 до 14. В системах, поддерживающих файловую систему FFS имена файлов могут содержать до 255 символов. В качестве символов следует использовать цифры, буквы латинского алфавита и символ ‘_’. Локальное имя файла хранится в соответствующем каталоге. Путь к файлу от корневого каталога называется полным именем файла. Если обращение к файлу начинается с символа "/", то считается, что указано полное имя файла и его поиск начинается с корневого каталога, в любом другом случае поиск файла начинается с текущего каталога.

У любого файла может быть несколько имен. Фактически, имя файла является ссылкой на файл, специфицированный номером описателя.

1.2. Регистрация в системе

Работа пользователя в системе начинается с того, что активизируется сервер терминального доступа getty, который запускает программу login, запрашивающую у пользователя имя и пароль.

Далее происходит проверка аутентичности пользователя в соответствии с той информацией, которая хранится в файле /etc/passwd. В этом файле хранятся записи, содержащие

Если пользователь зарегистрирован в системе и ввел правильный пароль, login запускает программу, указанную в /etc/passwd - регистрационный shell пользователя.

1.3. Пользователи системы и владельцы файлов

Пользователь системы - это объект, обладающий определенными правами, определяющими возможность запуска программ на выполнение, а также владение файлами. Единственный пользователь системы, обладающий неограниченными правами - это суперпользователь или администратор системы.

Система идентифицирует пользователей по т.н. идентификатору пользователя (UID - User Identifier). Каждый пользователь является членом одной или нескольких групп - списка пользователей, имеющих сходные задачи. Каждая группа имеет свой уникальный идентификатор группы (GID - Group Identifier) Принадлежность группе определяет совокупность прав, которыми обладают члены данной группы.

Права пользователя UNIX - это прежде всего права на работу с файлами. Файлы имеют двух владельцев - пользователя (user owner) и группу (group owner).

Соответственно атрибуты защиты файлов определяют права пользователя-владельца файла (u), права члена группы-владельца (g) и права всех остальных (o).

1.4. Перенаправление потоков и программные каналы

В ОС UNIX существует три стандартных потока: поток ввода, поток вывода и поток стандартного протокола (поток ошибок).

Перенаправление потоков позволяет изменить стандартный ввод (вывод):

<      – изменение источника стандартного ввода;

>, >>      – изменение приемника стандартного вывода.

Примеры:

cat > filename - перенаправление вывода программы cat в файл filename (если этот файл существует, то его прежнее содержимое будет утеряно);

cat >> filename - добавить содержимое вывода программы cat к содержимому файла filename;

cat < filename - сформировать стандартный ввод программы cat из содержимого файла filename.

Стандартные потоки - поток ввода, поток вывода и поток ошибок (поток протокола) имеют фиксированную нумерацию - 0, 1 и 2 соответственно. Эти номера (номера дескрипторов потоков) можно использовать в явном виде. Например, запись

prog 1>file

эквивалентна записи

prog >file

Для того, чтобы отличить имя потока от имени файла, перед номером потока ставится символ ‘&’:

prog >file 2>&1

Здесь происходит перенаправление стандартного потока вывода в файл file (>file). А кроме того, сообщения об ошибках также будут перенаправлены в файл file: запись 2>&1 означает перенаправление потока ошибок на стандартный поток вывода, который, в свою очередь, был перенаправлен в файл.

Замечание: анализ команды осуществляется интерпретатором справа налево: сначала происходи слияние потоков (2>&1), а затем перенаправляется стандартный поток вывода (1) в файл file.

В связи с этим бывает полезно использование псевдоустройства /dev/null, удаляющего все введенные в него символы. Это используется тогда, когда необходимо полностью игнорировать (подавить) выходные потоки.

Канал - это программное средство, связывающее процессы ОС UNIX буфером ввода/вывода. Запуск процессов в виде

$ процесс_1 | процесс_2 | ... | процесс_n

означает, что стандартный вывод процесса_1 будет замкнут на стандартный ввод процесса_2, стандартный вывод процесса_2 будет замкнут на стандартный ввод процесса_3 и т.д. При этом сначала создается канал, а потом на выполнение одновременно запускаются все процессы, и общее время их выполнения определяется более медленным процессом.

Пример:      ls | wc -l

Команда ls выводит на экран (стандартный поток вывода) список файлов текущего каталога, а команда wc -l считает количество строк во входном потоке (в файле, а если файл не указан – в стандартном входном потоке). Таким образом, объединение этих двух команд программным каналом позволяет посчитать количество файлов в текущем каталоге. Те же действия можно организовать так:

ls > buffer

wc -l < buffer

rm -f buffer

Итоговая таблица:

> file

Перенаправление стандартного потока вывода в файл file

>> file

Добавление в файл file данных из стандартного потока вывода

< file

Получение стандартного потока ввода из файла file

p1 | p2

Передача стандартного потока вывода программы p1 в поток ввода программы p2

n > file

Переключение потока вывода из файла с дескриптором n в файл file

n >> file

Добавление записей потока вывода из файла с дескриптором n в файл file

n > &m

Слияние потоков с дескрипторами n и m

2. КОМАНДНЫЙ ЯЗЫК СИСТЕМЫ UNIX. ИНТЕРПРЕТАТОР SHELL

2.1. Общие положения

Интерпретатор SHELL является оболочкой всей операционной системой и выполняет интерфейсные функции между пользователем и ОС. Он перехватывает и интерпретирует все команды пользователя, формирует и выводит ответные сообщения.

Помимо запуска на выполнение стандартных команд UNIX и исполняемых файлов, интерпретатор включает собственный язык, который по своим возможностям приближается к высокоуровневым языкам программирования. Этот язык позволяет создавать программы (shell-файлы, скрипты), которые могут включать операторы языка и команды UNIX. Такие файлы не требуют компиляции и выполняются в режиме интерпретации, но они должны обладать правом на исполнение (устанавливается с помощью команды chmod).

Общение пользователя с командным интерпретатором осуществляется вводом команд с клавиатуры после появления промпта (приглашения), обычно, символа '$'. Введенную последовательность символов интерпретатор будет рассматривать либо как имя внутренней команды, либо как имя исполняемого файла.

Процедуре (скрипту) shell могут быть переданы аргументы при запуске. Каждому из первых девяти аргументов ставится в соответствие позиционный параметр от $1 до $9 ($0 - имя самой процедуры), и по этим именам к ним можно обращаться из текста процедуры.

Прежде, чем начать рассмотрение некоторых операторов shell, следует обратить внимание на использование в командах некоторых символов.

\      знак отмены специального символа перевода строки, следующего непосредственно вслед за этим знаком.

‘’      одинарные кавычки: используются для обрамления текста: передаваемого как единый аргумент команды.

“”      двойные кавычки, используются для обрамления текста, содержащего имена переменных для подстановки ($имя) или стандартные команды, заключенные в символы тупого ударения (`команда`).

``      символы тупого ударения, служат для выполнения команды, заключенной между ними.

Кроме того, для удобства работы с файлами почти все командные интерпретаторы интерпретируют символы '?' и '*', используя их как шаблоны имен файлов (т.н. метасимволы):

? – один любой символ;

* – произвольное количество любых символов.

Например:      *.c – задает все файлы с расширением "c";

pr???.* – задает файлы, имена которых начинаются с "pr", содержат пять символов и имеют любое расширение.

Рассмотрим в качестве примера использование утилиты echo, которая только и умеет, что выводить в стандартный выходной поток переданные ей аргументы. Вывод на экран содержимого текущего каталога можно осуществить так:

echo “Текущий каталог: \

`pwd` \

`ls`”

А если ввести команду

echo *.?

то будут выведены все файлы с расширением из одного символа.

Переменные языка shell

Язык shell позволяет работать с переменными (без предварительного объявления). Имена переменных начинаются с буквы и могут включать буквы и цифры. Обращение к переменным начинается со знака '$'.

Пример. Переход к начальному каталогу пользователя:

cd $HOME

Оператор присваивания. Присвоение значений переменным осуществляется с помощью оператора ‘=’ без пробелов.

Пример:                        s=Hello

echo $s

Вычисление выражений осуществляется с помощью команды expr и арифметических и логических операторов:

арифметические

логические

+

сложение

=

равно

-

вычитание

!-

не равно

\*

умножение

\<

меньше

/

деление

\<=

меньше или равно

%

остаток от деления

\>

больше

 

 

\>=

больше или равно

Результат операций сравнения - вывод 1 (true) или 0 (false). Все операторы и имена переменных должны отделяться друг от друга пробелами.

Пример.

a=5 b=12

a=’expr $a + 4’

d=’expr $b - $a’

echo $a $b $d

Будет выведено:

9 12 3

Условные выражения. Ветвление вычислительного процесса осуществляется с помощью оператора if:

      if список_команд1

      then список_команд2

      [else список_команд3]

      fi

Список_команд - это одна или несколько команд (для задания пустого списка используется двоеточие - ‘:’). Список_команд1 предает оператору if код возврата последней команды из списка. Если он равен 0, то выполняются команды из списка_команд2, таким образом нулевой код возврата эквивалентен значению “истина”. В противном случае выполняются команды из списка_команд3, если он существует.

Проверка условия может осуществляется с помощью команды test. Аргументами этой команды могут быть имена файлов, числовые и нечисловые строки. Она используется в следующих режимах:

Проверка файлов:            test -ключ имя_файла

Ключи:      -r      файл существует и доступен для чтения;

            -w      файл существует и доступен для записи;

            -x      файл существует и доступен для исполнения;

            -f      файл существует и имеет тип ‘-‘, т.е. это обычный файл;

            -s      файл существует, имеет тип ‘-‘ и не пуст;

            -d      файл существует и имеет тип ‘d‘, т.е. это каталог.

Сравнение чисел:            test число1 -ключ число2

Ключи:      -eq      равно;

            -ne      не равно;

            -lt      меньше;

            -le      меньше или равно;

            -gt      больше

            -ge      больше или равно.

Сравнение строк:

test [-n] строка                  строка непуста;

test -z строка                  строка пуста;

test строка1 = строка2            строки равны;

test строка1 != строка2      строки не равны.

Построение циклов. В языке shell есть три типа циклов: while, until и for.

цикл while:

while список_команд1{;|перевод строки}

do список_команд2{;|перевод строки}

done

В условии учитывается код возврата последней выполненной команды из списка_команд1, при этом 0 интерпретируется как “истина”.

цикл until:

until список_команд1{;|перевод строки}

do список_команд2{;|перевод строки}

done

Проверка условия выполняется перед выполнением цикла. Учитывается код возврата последней выполненной команды из списка_команд1, при этом цикл выполняется до тех пор, пока код возврата не примет значение “истина”.

цикл for:

for переменная [in список_значений]{;|перевод строки}

do список_команд{;|перевод строки}

done

Переменной присваивается значение очередного слова из списка_значений и для этого значения выполняется список_команд. Количество итераций равно количеству цепочек символов в списке_значений, разделенных пробелами. Если слово in и список_значений опущены как необязательные, то переменной поочередно присваиваются значения параметров, переданных при запуске данной программы. В качестве списка можно использовать шаблоны имен файлов, тогда интерпретатор превращает этот шаблон в требуемый синтаксисом список имен файлов, удовлетворяющий шаблону.

Пример. Печать списка имен текстовых файлов из текущего каталога.

list=`ls *.txt`

for val in $list

do

      echo "$val"

done

2.2. Справочные команды

man [имя команды]

Альтернативой команды man в некоторых клонах UNIX является команда use:      use [имя команды]

Пример:

$ who

user1      tty4      Mar 11      18:46

user2      ty12      Mar 11      16:29

Выводится имя пользователя, номер терминала, дата и время начала работы этого пользователя. Команда who am i выведет информацию о самом пользователе.

2.3. Команды работы с каталогами

$ ls [-ключи] [имя каталога]

Если имя каталога не указано, выводится содержимое текущего каталога. Ключи определяют формат выдачи, например:

-l – вывод полной информации о каждом файле;

-a – вывод полного списка файлов, включая "." и "..";

-t – сортировка списка по времени создания;

-C – вывод списка в несколько колонок по алфавиту и т.п.

Пример:      $ ls -l

drwxrwxrwx

6

user1

user1

496

Mar 10 12:01

tmp

-rw-rw-r—

1

user1

user1

156

Mar 12 15:26

file.c

-rwxrwx—x

2

root

root

4003

Apr 01 11:44

pe.out

права доступа

Число ссылок

имя влад.

имя группы влад.

длина файла, байт

дата последней модификации

локальное имя файла

$ cd [полное_имя_каталога]

При этом указанный каталог станет текущим. Команда cd без аргументов восстановит в качестве текущего каталога начальный каталог пользователя.

$ mkdir [-ключи] имя_нового_каталога

Для создания нового каталога пользователь должен иметь право записи в родительский каталог текущего каталога.

$ rmdir список_каталогов

Система не позволит удалить каталог, если он не пуст или если у пользователя нет прав записи в него. Текущий каталог не должен принадлежать поддереву удаляемых каталогов.

2.4. Команды работы с файлами

$ rm [-ключи] список_файлов

Эта команда удаляет ссылки на файлы (то есть локальные имена файлов), если у пользователя есть право записи в каталог, содержащий эти имена. Если удаляемый файл защищен от записи, команда запрашивает подтверждение на удаление файла. Ключи:

$ chmod атрибуты список_файлов

Атрибуты файла могут быть заданы разными способами:

  1. буквенной кодировкой. Атрибуты защиты обозначаются так:

Категории пользователей задаются следующим образом:

Производимая операция кодируется с помощью таких символов:

Пример. Разрешить доступ по чтению и записи к файлам с именем tops владельцу и группе-владельцу:

$ chmod ug+rw tops.*

  1. в виде восьмеричного числа. Числовые значения атрибутов защиты кодируются трехразрядным восьмеричным числом, где существование соответствующего атрибута соответствует наличию единицы в двоичном эквиваленте восьмеричной цифры этого числа, а отсутствие атрибута – нулю. Например:

Пример. Установить атрибуты чтения и записи для владельца и группы-владельца и только чтения для остальных пользователей:

$ chmod 0664 gb??.doc

$ cat [-ключи] [входной_файл1[входной_файл2...]]

Команда по очереди читает указанные входные файлы, если их несколько, объединяет и выводит считанные данные в стандартный поток вывода (на экран). С помощью перенаправления потоков (программных каналов) команда cat может быть использована для выполнения разнообразных операций.

Примеры:

  1. $ cat > file1      – в файл file1 помещается текст, набираемый на клавиатуре. Если до этого файл file1 не существовал, он будет создан; если существовал, его первоначальное содержимое будет утрачено. Окончание ввода текста происходит при нажатии комбинации клавиш Ctrl+D.
  2. $ cat file1 > file2      – содержимое файла file1 копируется в файл file2. Файл file1 при этом остается без изменений.
  3. $ cat file1 file2 > result      – содержимое file2 будет добавлено к содержимому file1 и помещено в файл result.
  4. $ cat file1 >> file2      – содержимое файла file1 добавляется в конец файла file2.

$ cp вх_файл_1 [вх_файл_2 [...вх_файл_n]] вых_файл

Эта команда имеет два режима использования:

Пример. Скопировать два файла из текущего каталога в указанный с теми же именами:

$ cp f1.txt f2.txt ../usr/petr

$ ls ../usr/petr

f1.txt

f2.txt

$ mv вх_файл_1 [вх_файл_2 [...вх_файл_n]] вых_файл

Отличие команды пересылки от команды копирования состоит только в том, что входные файлы после выполнения команды уничтожаются.

Пример. Перенести файлы с расширением ".c" из указанного каталога в текущий:

$ mv petr/*.c .

$ ln вх_файл_1 [вх_файл_2 [...вх_файл_n]] вых_файл

Эта команда имеет два режима использования:

Пример:

$ ls

file1

$ ln file1 file2

$ ls

file1

file2

2.5. Команды работы с текстовыми файлами

$ grep [-ключи] подстрока список_файлов

Найденные строки выводятся на стандартный вывод в формате, определяемом ключами. Если файлов несколько, то перед каждой строкой выводится имя соответствующего файла. Ключи:

$ wc [-lwc] [список_файлов]

Подсчет строк – ключ -l, слов – ключ -w и символов – ключ -c (по умолчанию -lwc). Если список файлов пуст, то подсчет ведется в стандартном потоке ввода.

$ sort [-ключи] список_файлов

Эта команда сортирует входные файлы по строкам в соответствии с увеличением кодов символов. Ключи:

$ cmp файл_1 файл_2

Выводит номер символа и номер строки (в текстовых файлах), в которой впервые встречается расхождение во входных файлах. Работает с любыми файлами.

$ diff файл_1 файл_2

Выводит все строки, в которых встречаются расхождения между входными файлами. Работает только с текстовыми файлами.

find список_каталогов условия_поиска

Команда последовательно просматривает все поддеревья, начинающиеся с одного из каталогов, указанных в списке каталогов, анализирует их атрибуты, и если они удовлетворяют условиям поиска: выполняет действия, заданные в условиях_поиска.

В команде может быть задано множество условий поиска, необходимые комбинации которых объединяются в булевское выражение с помощью логических операций:

! условие            отрицание условия;

пробел             соответствует операции “И”;

-o                  операция “ИЛИ”;

\( выражение \)      булевское выражение в скобках

Перечислим некоторые опции, задающие условия (при этом условимся обозначать через n положительное десятичное число, +n - любое положительное число, строго большее n, -n - любое положительное число, строго меньшее n):

-name имя_файла            истинно для файлов с именем имя_файла; в задаваемом имени допускается использование метасимволов;

-perm 8-ричный_код      истинно для файлов с указанным кодом прав доступа;

-type {f|d|b|c|p}      истинно для файлов указанного типа (f - обычный файл, d - каталог, b - блок-ориентированный специальный файл, c - байт-ориентированный специальный файл, p - именованный канал);

-print            всегда истинно; вызывает печать маршрутного имени файла;

-size n[c]      истинно для файлов с длиной n. По умолчанию длина задается в блоках по 512 байт, а если после длины ставится символ c, то в байтах;

-exec команда      истинно, если команда, выполняющаяся при наличии данного условия, возвращает нулевой код завершения. Если в тексте команды должно быть указано имя текущего проверяемого файла, то вместо него пишут {}. В конце команды должна стоять экранированная точка с запятой: ‘\;’;

-links n      истинно для файлов с числом ссылок n.

Примеры:                  $find / -type f -links +1 -print

Выводятся полные маршрутные имена файлов корневого каталога, на которые имеется более одной ссылки.

$find / -type f -size +2 -exec ls -l {}\;

Выводятся листинги с указанием длины в блоках (по 1024 байта) для файлов корневого каталога, длина которых в блоках по 512 байт превышает 2.

$find /dev \( -type d -o -type b \) -print

Выводятся имена каталогов или специальных файлов устройств блок-ориентированного типа из каталога /dev и его подкаталогов

find / -name ‘*.a’ -exec ar -t {} \; |grep console

В этой сложной команде ищутся файлы с расширением ‘.a’ (архивы или библиотеки), происходит просмотр их содержимого (-exec ar -t {}) и выводятся строки, содержащие подстроку ‘console’ (grep console)

Запуск редактора: vi [+[n]] имя_файла

+            вывести на экран конец файла;

n            вывести на экран текст файла, начиная со строки n.

Текстовый полноэкранный редактор vi работает в двух основных режимах: в режиме “ввод текста” и в режиме “команда”.

Режим “ввод текста”. В этот режим редактор переводится с помощью клавиш <a> и <i>:

<a>            набор текста в текущую строку;

< i >            вставка текста в текущую строку перед курсором;

<ESC>            выход из режима “ввод текста” в режим “команда”.

Режим “команда”. Это - основной режим редактирования текста:

<x>            уничтожение текущего символа, выделенного курсором;

<r>      замена текущего символа на символ, набранный вслед за командой <r>;

<s>            замена одного или нескольких символов текстом. Например: 2sTEXT - замена двух текущих символов на слово TEXT;

<o>            вставить пустую строку после текущей;

[n]<dw>      уничтожить текущее слово или n слов;

[n]<dd>      уничтожить текущую строку или n строк.

Выход из редактора

<ESC>:wq!            Выход с сохранением;

<ESC>:q!            Выход без сохранения.

2.6. Команды работы с процессами

имя_процесса [-ключи] [параметры] &

При выполнении этой команды следующее приглашение ОС появится сразу же после запуска процесса (не дожидаясь его завершения). Фоновый процесс не допускает ввода с клавиатуры и выводит сообщения на экран, нарушая целостность ввода и вывода работающего процесса.

nohup имя_процесса [-ключи] [параметры]

Эта команда перенаправляет поток вывода фонового процесса в файл nohup.out.

ps [-ключи]

При отсутствии ключей будет выведен список процессов самого пользователя (идентификатор процесса, номер терминала и время процессора, затраченное на процесс). Ключи:

kill -номер_сигнала идентификатор_процесса

Для принудительного завершения процесса ему посылается сигнал номер 9, который невозможно проигнорировать или обработать в процессе никаким иным образом, кроме немедленного завершения.

3. ВЫПОЛНЕНИЕ ЛАБОРАТОРНОЙ РАБОТЫ

Перед началом выполнения работы необходимо получить у преподавателя имя (идентификатор пользователя) и пароль.

При запуске система запрашивает login (идентификатор пользователя) и password (пароль). При успешном вводе появляется приглашение (обычно – $); в противном случае необходимо еще раз повторить ввод. (Пароль при вводе на экране не отображается).

Лабораторная работа посвящена изучению интерпретатора команд UNIX. Список команд, обязательных для изучения, приведен в п.2. Обратите особое внимание на перенаправление потоков ввода/вывода и программные каналы.

4. ЗАДАНИЯ НА ЛАБОРАТОРНУЮ РАБОТУ

  1. Посчитать количество пользователей в системе.
  2. Отсортировать список файлов текущей директории в обратном порядке и записать его в файл.
  3. Посчитать количество файлов текущего каталога, содержащих подстроку "include".
  4. Посчитать, сколько раз пользователь X вошел в систему.
  5. Отсортировать список текстовых файлов текущей директории в алфавитном порядке и записать его в файл.
  6. Удалить из текущего каталога все файлы, содержащие подстроку "text".
  7. Объединить все файлы с расширением ".txt" в один файл.
  8. Посчитать, сколько процессов запущено с данного терминала.
  9. Вывести на экран отсортированный в алфавитном порядке список файлов, содержащих подстроку "include".
  10. Написать скрипт, удаляющий все файлы содержащие кодовую сигнатуру из указанного каталога.

Внимание! При выполнении заданий необходимо использовать перенаправление ввода/вывода и программные каналы.

 

ЛАБОРАТОРНАЯ РАБОТА №2. ФАЙЛОВАЯ СИСТЕМА UNIX

Лабораторная работа посвящена изучению принципов организации файловой системы UNIX и приобретению навыков написания программ работы с файлами.

1. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

Файловая система – это ключевое звено, обеспечившее успешное применение UNIX. Основной особенностью файловой системы UNIX является то, что все, с чем работает ОС UNIX, она воспринимает в виде файла. Таким образом, файл является единой универсальной структурой данных, в рамках которой реализуется любая операция ввода-вывода.

1.1. Структура файловой системы

Файловая система ОС UNIX имеет иерархическую структуру, образующую дерево каталогов и файлов. Корневой каталог обозначается символом "/", путь по дереву каталогов состоит из имен каталогов, разделенных символом "/", например:

/home/work/document

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

Каждый файл ОС UNIX может быть однозначно специфицирован некоторой структурой данных, называемой описателем файла или дескриптором. Эта структура описана в файле <fcntl.h>, она занимает 64 байта и содержит следующую информацию:

struct dinode

{      unsigned short di_mode;      /* режим доступа и тип файла */

short di_nlink;            /* счетчик числа ссылок на файл */

short di_uid;            /* идентификатор его владельца */

short di_gid;            /* идентификатор группы */

off_t di_size;            /* счетчик числа байт в файле */

char di_addr[40];      /* указатели на блоки диска,

в которых хранится сам файл */

time_t di_atime;      /* дата последнего доступа */

time_t di_mtime;      /* дата последней модификации */

time_t di_ctime;      /* дата создания */

}

Поле di_mode состоит из 16-ти разрядов:

Рис.1. Режим доступа и тип файла

Поле di_addr используется для хранения указателей местоположения блоков диска, содержащих информацию, помещенную в данный файл. В этом поле может храниться 13 указателей, из которых первые 10 относятся к первым десяти блокам файла. Если файл занимает больше места, то в 11-й указатель заносится информация о местоположении первичного блока косвенности, состоящего из ста двадцати восьми 32-битных указателей на блоки файла; 12-й указатель указывает на вторичный блок косвенности, содержащий 128 указателей местоположения первичных блоков косвенности, а 13-й указатель, соответственно, указывает на местоположение третичного блока косвенности, включающего 128 указателей вторичного блока косвенности. Таким образом, используя эту схему адресации, можно обращаться к файлу, состоящему не более чем из (128x128x128+128x128+128+10) блоков. Все эти рассуждения справедливы для блоков размером 512 (128x4) байт.

Обращение к файлу происходит по имени. Локальное имя файла – это набор произвольных символов. Если в среди них встречается точка, то за ней следует так называемое расширение, которое обычно служит для определения типа файла. Например, файлы, хранящие текст, чаще всего имеют расширение "txt" или "doc" (title.doc, book.txt и т.д.), файлы с текстом программ на языке С – расширение "c" (progr.c, code.c и т.п.), исполняемые файлы – расширение "out" или вовсе без расширений. Расширений может быть несколько (например, имя "progr.c.b" может означать старую версию (bak-файл) программы на языке С).

Локальное имя файла хранится в соответствующем каталоге. Путь к файлу от корневого каталога называется полным именем файла. Если обращение к файлу начинается с символа "/", то его поиск начинается с корневого каталога, в любом другом случае поиск файла начинается с текущего каталога. У любого файла может быть несколько имен. Фактически, имя файла является ссылкой на файл, специфицированный номером описателя. Таким образом, располагая имена одного и того же файла в разных каталогах можно в каждом каталоге иметь возможность обращаться к файлу напрямую, а не с помощью указания полного пути.

1.2. Типы файлов

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

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

Каталог – это файл особого типа, отличающийся от обычного файла наличием структуры и ограничением по записи: осуществить запись в каталог может только ядро ОС UNIX. Каталог устанавливает соответствие между файлами (точнее, номерами описателей) и их локальными именами. Пример каталога для файловой системы ОС UNIX System V – Рис.2 (2 байта – номера описателей, 14 байтов – локальные имена).

Номер описателя

Имя файла

5412

.

81

..

3009

bin

3413

text.txt

0

cross.c

3601

move.o

Рис.2. Пример каталога UNIX System V

Номер описателя, соответствующий имени ".", – это ссылка на файл, в котором содержится информация о самом каталоге. Номер описателя, соответствующий имени "..", – это ссылка на родительский каталог текущего каталога. Номер описателя равный 0 означает, что ссылка на соответствующий файл удалена из каталога и эта запись каталога считается свободной.

Совокупность всех каталогов специфицирует структуру файловой системы в целом.

Специальный файл – это файл, поставленный в соответствие некоторому внешнему устройству и имеющий специальную структуру. Его нельзя использовать для хранения данных как обычный файл или каталог, но над ним можно производить те же операции, что и над любым другим. При этом ввод/вывод информации в этот файл будет соответствовать вводу с внешнего устройства или выводу на него.

Канал – это программное средство, связывающее процессы ОС UNIX буфером ввода/вывода (см. лаб. работу №1).

1.3. Управление файлами

ОС UNIX поддерживает операции ввода-вывода с помощью набора взаимосвязанных таблиц. Основной из них считается таблица описателей файлов (FDT). Она представляет собой хранящуюся в оперативной памяти ЭВМ структуру данных, элементами которой являются копии описателей файлов, к которым была осуществлена попытка доступа. Каждому элементу таблицы описателей файлов обязательно соответствует один или несколько элементов системной таблицы файлов (SFT). Элемент таблицы файлов содержит информацию о режиме открытия файла и положении указателя чтения-записи. Таким образом, каждый файл может быть одновременно открыт несколькими независимыми процессами, и при каждом открытии файла количество элементов таблицы файлов будет увеличиваться на единицу.

Если процессы связаны родственными отношениями, то процесс-потомок, порожденный системным вызовом fork, унаследует все открытые файлы процесса-предка. Это осуществляется с помощью таблицы открытых файлов процесса, которая создается сразу после порождения процесса, содержит информацию только о файлах, открытых данным процессом и передается процессу-потомку в момент его порождения.

Для примера рассмотрим следующую последовательность системных вывозов:

fd1 = open("/etc/passwd",O_RDONLY);

fd2 = open("local",O_RDWR);

fd3 = open("/etc/passwd",O_WRONLY);

На Рис. 3 показана взаимосвязь между таблицей описателей файлов, таблицей файлов и таблицей открытых файлов процесса. Каждый вызов функции open возвращает процессу дескриптор файла, а соответствующая запись в таблице открытых файлов процесса указывает на уникальную запись в таблице файлов ядра, даже если один и тот же файл ("/etc/passwd") открывается дважды. Записи в таблице файлов для всех экземпляров одного и того же открытого файла указывают на одну запись в таблице описателей файлов, хранящихся в памяти. Процесс может обращаться к файлу "/etc/passwd" с чтением или записью, но только через дескрипторы файла, имеющие значения 3 и 5 (Рис.3). Ядро запоминает разрешение на чтение или запись в файл в строке таблицы файлов, выделенной во время выполнения функции open.

Рис.3. Структуры данных после открытия файлов одним процессом

Предположим, что другой процесс выполняет следующий набор операторов:

fd1 = open("/etc/passwd",O_RDONLY);

fd2 = open("private",O_RDONLY);

На Рис. 4 показана взаимосвязь между соответствующими структурами данных, когда оба процесса (и больше никто) имеют открытые файлы. Снова результатом каждого вызова функции open является выделение уникальной точки входа в таблице открытых файлов процесса и в таблице файлов ядра, и ядро хранит не более одной записи на каждый файл в таблице описателей файлов, размещенных в памяти.

Рис. 4. Структуры данных после того, как два независимых процесса открыли файлы

Запись в таблице открытых файлов процесса по умолчанию хранит смещение в файле до адреса следующей операции ввода/вывода и указывает непосредственно на точку входа в таблице описателей для файла, устраняя необходимость в отдельной таблице файлов ядра.

Вышеприведенные примеры показывают взаимосвязь между записями таблицы открытых файлов процесса и записями в таблице файлов ядра типа “один к одному”. Однако, таблица файлов, реализованная как отдельная структура, позволяет совместно использовать один и тот же указатель смещения нескольким пользовательским дескрипторам файла. В системных вызовах dup (см. раздел "Программирование операций ввода-вывода") и fork (лабораторная работа №3) при работе со структурами данных допускается такое совместное использование.

Первые три пользовательских дескриптора (0, 1 и 2) именуются дескрипторами файлов стандартного ввода, стандартного вывода и стандартного потока ошибок. Процессы в системе UNIX по договоренности используют дескриптор файла стандартного ввода при чтении вводимой информации, дескриптор файла стандартного вывода при записи выводимой информации и дескриптор стандартного файла ошибок для записи сообщений об ошибках. В операционной системе нет никакого указания на то, что эти дескрипторы файлов являются специальными. Группа пользователей может условиться о том, что файловые дескрипторы, имеющие значения 4, 6 и 11, являются специальными, но более естественно начинать отсчет с 0 (как в языке Си). Принятие соглашения сразу всеми пользовательскими программами облегчит связь между ними при использовании каналов.

Обычно операторский терминал служит и в качестве стандартного ввода, и в качестве стандартного вывода, и в качестве стандартного устройства вывода сообщений об ошибках.

Вызов fork порождает процесс, являющийся потомком по отношению к тому процессу, из которого осуществлен вызов. Процесс-потомок является точной копией процесса-предка за исключением номера самого процесса и значения, возвращаемого вызовом fork. При этом потомок получает к ранее открытым файлам доступ того же типа, что и предок (говорят, что процесс наследует открытые файлы). Родственные процессы общаются с общим файлом через один указатель чтения/записи, и если один из процессов прочитал или записал данные в файл, то значение указателя чтения/записи изменится для всех родственных процессов, имеющих доступ к этому файлу. Естественно, это не относится к файлам, которые были открыты родственными процессами после вызова fork: в этом случае каждый процесс обращается к файлу через собственный указатель.

Для примера рассмотрим следующую последовательность системных вызовов и состояние файловых таблиц после их выполнения (Рис.5):

fd1 = open("/etc/passwd",O_RDONLY);

pid = fork();

fd2 = open("private",O_RDWR);

Первый вызов open выполняется до вызова fork, он создает записи, относящиеся к файлу "/etc/passwd", во всех файловых таблицах. При выполнении вызова fork процесс-потомок получает копию таблицы открытых файлов процесса, а в записях таблиц файлов и описателей файлов счетчики ссылок на файл "/etc/passwd" увеличиваются на единицу и становятся равным 2.

Рис. 5. Структуры данных после того, как два родственных процесса открыли файлы

Дополнительная запись в таблицу файлов не добавляется, оба процесса имеют доступ к файлу через один указатель чтения/записи. Второй вызов open выполняется после вызова fork, то есть тогда, когда существуют уже два процесса – предок и потомок. Каждый из них выполняет открытие файла независимо от другого, поэтому новые записи добавляются во все таблицы (запись в таблице описателей одна на файл, но счетчик ссылок на файл равен числу открывших файл процессов).

Закрытие файла уменьшает число ссылок на файл, и только когда оно становится равным 0, происходит удаление соответствующих записей из таблиц.

2. ПРОГРАММИРОВАНИЕ ОПЕРАЦИЙ ВВОДА-ВЫВОДА

Системные вызовы представляют собой единственное средство, реализующее интерфейс между пользовательскими программами и ядром ОС UNIX. Всякая операция ввода/вывода для пользователя – это операция ввода/вывода в файл. Рассмотрим наиболее часто используемые из системных вызовов.

OPEN. Открывает файл для получения доступа к нему:

int open(char *pathname, int flags, mode_t mode)

Возвращает положительное целое число, так называемый пользовательский дескриптор файла fd, который в дальнейшем используется для обращения к этому файлу. pathname - указатель на строку символов, содержащую полное имя файла. mode - режим открытия файла (по чтению, записи и др.) Если нет возможности открыть файл, open возвращает -1. flags определяет режим открытия файла (O_CREAT, O_TRUNC, O_RDONLY, O_WRONLY и т.д.), mode задает права доступа к создаваемому файлу.

CLOSE. Закрывает файл, уничтожает связь между пользовательским дескриптором файла и самим файлом:

void close(int fd)

Параметр fd – дескриптор файла, возвращенный вызовом open. Функция close уничтожает связь между пользовательским дескриптором файла и самим файлом и уменьшает на 1 значения счетчиков в относящихся к нему записях файловых таблиц. Если значение счетчика становится равным 0, то данная запись считается свободной. Если равно 0 значение счетчика в записи системной таблицы описателей файлов, файл закрывается.

STAT и FSTAT. Эти системные вызовы позволяют получить информацию о файле, не осуществляя явного доступа к нему:

int stat(char *path, struct stat *statbuf)

int fstat(int fd, struct stat *statbuf)

Вызов stat предоставляет информацию по имени файла, а fstat – по номеру дескриптора открытого файла. Информация помещается в структуру stat, описанную ниже:

struct stat

{      dev_t st_dev;

ino_t st_ino;

ushort st_mode;      /* режим доступа и тип файла */

short st_nlink;      /*счетчик числа ссылок на файл*/

ushort st_uid;            /*идентификатор его владельца */

ushort st_gid;            /* идентификатор группы */

dev_t st_rdev;            /* тип устройства */

off_t st_size;            /* размер файла в байтах */

time_t st_atime;      /* дата последнего доступа */

time_t st_mtime;      /* дата последней модификации */

time_t st_ctime;      /* дата создания */

}

Для детализации информации в поле st_mode используются следующие макросы:

#define S_IFMT      0170000      /* тип файла */

#define S_IFDIR      0040000      /* каталог */

#define S_IFCHR      0020000 /*байториентированный спец.файл */

#define S_IFBLK      0060000 /*блокориентированный спец.файл */

#define S_IFREG      0100000      /* обычный файл */

#define S_IFIFO      0010000      /* дисциплина FIFO */

#define S_ISUID      04000      /* идентификатор владельца */

#define S_ISGID      02000      /* идентификатор группы */

#define S_ISVTX      01000      /*сохранить свопируемый текст */

#define S_IREAD      00400      /* владельцу разрешено чтение */

#define S_WRITE      00200      /* владельцу разрешена запись */

#define S_IEXEC      00100      /*владельцу разрешено исполнение */

Пример использования вызова stat:

struct stat stbuf;

char *filename = ”myfile”;

. . . . . . . . . . . .

stat(filename, &stbuf);

if ((stbuf.st_mode & S_IFMT) == S_IFDIR)

printf("%s является каталогом", filename);

LSEEK. Перемещает указатель файла с пользовательским дескриптором fd на offset байт:

long lseek(int fd, long offset, int fromwhere)

Параметр fromwhere определяет положение указателя файла перед началом перемещения:

SEEK_SET – от начала файла;

SEEK_CUR – от текущей позиции указателя;

SEEK_END – от конца файла.

READ. Осуществляет чтение из открытого файла указанного количества символов в буфер:

int read(int fd, void *buffer, unsigned count)

Возвращает количество реально прочитанных байт num или отрицательный код ошибки. При этом указатель чтения/записи перемещается на num байт.

WRITE. Осуществляет запись в открытый файл указанного количества символов из буфера:

int write(int fd, void *buffer, unsigned count)

Возвращает количество реально записанных num байт или отрицательный код ошибки. При этом указатель чтения/записи перемещается на num байт.

DUP и DUP2. Эти системные вызовы дублируют пользовательский дескриптор файла:

int dup(int handle);

int dup2(int oldhandle, int newhandle);

fd1 = dup(handle);

fd2 = dup2(oldhandle, newhandle);

Копия пользовательского дескриптора позволяет осуществлять к файлу доступ того же типа и с использованием того же указателя чтения/записи, что и с помощью оригинального дескриптора.

Вызов dup возвращает первый свободный номер дескриптора fd1 или -1, если указанный дескриптор handle не соответствует открытому файлу или нет свободных номеров.

Вызов dup2 возвращает дескриптор newhandle как копию дескриптора oldhandle или -1, если указанный дескриптор oldhandle не соответствует открытому файлу. Если newhandle до этого указывал на открытый файл, этот файл в результате вызова dup2 будет закрыт.

3. ПРИМЕРЫ ПРОГРАММ РАБОТЫ С ФАЙЛАМИ

Пример 1. Запись в файл и чтение из файла. Обратите внимание на обработку параметров командной строки.

/*--------------------------------------------------*/

/* Программа воспринимает в качестве параметра */

/* командной строки имя рабочего файла. Если файл */

/* не существует, он будет создан, если существует, */

/* его содержимое будет потеряно. */

/*--------------------------------------------------*/

#include <stdio.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <fcntl.h>

int fd;

int f1()

{     static int j = 1;

      if (j > 10) return 0;

      write(fd, &j, sizeof(int));

      printf("write %d -- %d\n", fd, j++);

      return 1;

}

void f2()

{     int i;

      lseek(fd,-sizeof(int), 1);

      read(fd, &i, sizeof(int));

      printf("read %d -- %d\n", fd, i);

}

void main(int argc, char *argv[])

/* argc – количество параметров командной строки.      */

/* *argv[] – указатели на строки параметров            */

{      if (argc < 2) puts("Format: rw filename");

      else

      {      fd = open(argv[1], O_CREAT | O_RDWR);

            while(f1()) f2();

            close(fd);

      }

      exit(0);

}

Пример 2. Дублирование дескриптора файла.

/*---------------------------------------------*/

/* Перенаправление стандартного вывода в файл. */

/*---------------------------------------------*/

#include <io.h>

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

void main(void)

{      int outf, std_out;

      char *str1 = "Вывод строки в файл ",

      *str2 = "Вывод строки на экран";

      std_out = dup(1);

      /* закрытие стандартного вывода */

      close(1);

      outf = open("1.dat", O_WRONLY);

      puts(str1);

      write(std_out,str2,strlen(str2));

      /* восстановление предыдущих значений */

      close(outf);

      outf = open("dev\tty", O_WRONLY);

      close(std_out);

      exit(0);

}

4. ВЫПОЛНЕНИЕ ЛАБОРАТОРНОЙ РАБОТЫ

Выполнение работы заключается в написании и отладке программы по одному из вариантов задания (п.5). Ввод текста программы и его редактирование производится с помощью любого редактора UNIX (vi, ed и др.). Компиляция программы осуществляется с помощью следующего вызова:

$ cc имя_файла.с

На выходе получается исполняемый файл "a.out" или список сообщений об ошибках. Расширение указывать обязательно. Если запустить компилятор с опицией -o, можно указать произвольное имя исполняемого файла:

$ cc -o имя_исполняемого_файла имя_файла.c

Для сдачи лабораторной работы требуется работающая программа, распечатка программы с комментариями и аннотацией (фамилия, номер группы, номер варианта и задание), а также знание теоретического материала.

5. ЗАДАНИЯ НА ЛАБОРАТОРНУЮ РАБОТУ

  1. Написать программу, считывающую из входного файла байты с N1 по N2 и с N3 по N4 и записывающую эти байты в выходной файл.
  2. Написать программу, меняющую в файле местами группы байт с N1 по N2 и с N2 по N3.
  3. Написать программу, переписывающую из входного файла каждый n-й байт в выходной файл.
  4. Написать программу, переписывающую все байты входного файла в выходной файл в обратном порядке.
  5. Написать программу, осуществляющую поиск заданного шаблона (последовательности символов) в файле. При обнаружении шаблона заменить его на последовательность символов с кодом 0 такой же длины, что и длина шаблона.
  6. Написать программу, осуществляющую поиск в файле последовательностей, состоящих из двух и более пробелов, и удаление всех из них, кроме первого.
  7. Написать программу кодировки входного файла на основании кодового слова с возможностью декодирования (алгоритм сложения по модулю два).
  8. Написать программу, осуществляющую подсчет количества строк в текстовом файле и запись полученного числа в начало этого файла первой строкой.
  9. Написать программу, которая осуществляет подсчет количества слов в текстовом файле и записывает полученное число в начало этого файла первой строкой.
  10. Написать программу, осуществляющую замену в файле всех символов с кодами от C1 по C2 на пробелы.
  11. Написать программу, разбивающую текстовый файл на страницы по N строк, то есть добавляющую в файл после каждых N строк символ перевода страницы (код 12).
  12. Написать программу, переводящую текстовый файл из формата UNIX в формат DOS и обратно, т.е. добавляющую (или удаляющую) после символа перевода строки (код 10) символ возврата каретки (код 13).
  13. Написать программу, выводящую в файл протокола список файлов указанной директории. Если имя файла-протокола не указано, список выводится на экран.
  14. Написать программу, определяющую количество файлов в поддереве каталогов, начиная с указанной директории.
  15. Написать программу, устанавливающую биты разрешения доступа по исполнению каждому файлу в указанной директории, если для этого файла разрешено исполнение хотя бы для одной группы пользователей.
  16. Написать программу, выводящую в файл протокола список файлов указанного каталога, созданных или модифицированных в текущий день.
  17. Написать программу, выводящую в файл список имен владельцев файлов в указанном каталоге.
  18. Написать программу, выводящую в файл протокола список файлов из указанного каталога, имеющих n и более ссылок.
  19. Написать программу, выводящую содержимое входного файла на экран или в выходной файл (если указано его имя), а сообщения об ошибках – в любом случае на экран, используя дублирование потоков (dup).
  20. Написать программу, вводящую N байт из стандартного входного потока или из входного файла, если он указан, и запрашивающую количество байт N с клавиатуры (с использованием дублирования потоков (dup)).
  21. Написать программу, выводящую содержимое входного файла на экран и дублирующую протокол (stderr) на экран с использованием дублирования потоков (dup).
  22. Написать программу, создающую файл, занимающий на диске N блоков.
  23. Написать аналог утилиты grep.
  24. Написать аналог утилиты find.

Примечание. Все параметры вводятся в командной строке

 

 

 

БИБЛИОГРАФИЧЕСКИЙ СПИСОК

  1. Забродин Л.Д. UNIX. Введение в командный интерфейс. – М.: ДИАЛОГ-МИФИ, 1994. – 144 с.
  2. Дансмур М., Дейвис Г. Операционная система UNIX и программирование на языке Си: Пер. с англ. – М.: Радио и связь, 1989. – 192 с.
  3. Керниган Б.В., Пайк Р. UNIX – универсальная среда программирования: Пер. с англ. – М.: Финансы и статистика, 1992. – 304 с.
  4. Робачевский А.М. Операционная система UNIX. – СПб.: BHV – Санкт-Петербург, 1997. – 528 с.
  5. Т.Чан Системное программирование на C++ для UNIX. /Пер. с англ. -К.: Издательская группа BHV, 1997. - 592 с.

 

 

Учебное издание

 

 

КОМАНДНЫЙ ИНТЕРПРЕТАТОР UNIX

ФАЙЛОВАЯ СИСТЕМА UNIX

Составители:       КАРПОВ Валерий Эдуардович

КАРПОВА Ирина Петровна

 

 

 

 

 

 

Редактор

Технический редактор

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Подписано в печать .02. Формат 60ґ 84/16. Бумага офсетная № 2.

Ризография. Усл.-печ.л.__. Уч.-изд.л.__. Изд. № __. Тираж 50 экз.

Заказ.

Московский государственный институт электроники и математики.

109028, Москва, Б. Трехсвятительский пер. 3/12.

Отдел оперативной полиграфии Московского государственного

института электроники и математики. 113054,

ул. М. Пионерская, 12.