- •Кафедра программного обеспечения информационных технологий
- •«Операционные системы и системное программирование»
- •40 01 01
- •Содержание
- •Введение
- •Разработка программ в ос unix
- •1.1 Отличительные черты ос unix
- •1.2 Основы архитектуры операционной системы unix
- •1.3 Ядро системы
- •1.4 Пользователи системы, атрибуты пользователя
- •1.5 Системные вызовы и функции стандартных библиотек
- •1.6 Описание программы, переменные окружения
- •1.7 Аргументы и опции программы
- •1.8 Обработка ошибок
- •2 Файлы и файловая система
- •2.1 Файлы
- •2.2 Типы файлов
- •2.2.1 Обычные файлы
- •2.2.2 Каталоги
- •2.2.3 Файлы символичной связи (ссылки)
- •2.2.4 Файлы устройства
- •2.2.5 Именованные каналы
- •2.2.6 Сокеты
- •2.3 Владельцы файлов и права доступа к файлу
- •2.4 Дополнительные атрибуты файла
- •2.5 Файловый ввод/вывод
- •Открытие файла
- •2.6 Мультиплексированный ввод/вывод
- •2.7 Векторный ввод/вывод
- •2.8 Файлы, отображающиеся в памяти
- •2.9 Каталоги, работа с каталогами
- •2.9.1 Создание каталога
- •2.9.2 Удаление каталога
- •2.9.3 Чтение информации из каталога
- •2.9.4 Закрытие каталога
- •2.10 Создание жестких ссылок
- •2.11 Символическая ссылка
- •2.12 Удаление ссылки (или имени файла)
- •2.13 Переименование файла
- •2.14 Файловая система ос unix
- •2.14.1 Организация файловой системы ext2
- •2.15 Файлы устройств
- •3 Процессы
- •3.1 Виды процессов
- •3.2 Создание процесса
- •3.3 Вызовы семейства exec
- •3.4 Функции завершения процесса
- •3.5 Ошибки
- •3.6 Копирование при записи
- •3.7 Системные вызовы ожидания завершения процесса
- •3.8 Системный вызов system
- •3.9 Основные параметры, передаваемые процессу
- •3.10 Сеансы и группы процессов
- •4 Взаимодействие процессов
- •4.1 Сигналы
- •4.1.1 Отправка (генерация) сигнала
- •4.1.2 Наборы сигналов
- •4.1.3 Блокировка сигналов
- •4.2 Неименнованные каналы (трубы)
- •4.2.1 Размер канала и взоимодействие процессов при передаче данных
- •4.3 Именнованные каналы
- •4.4 Дополнительные средства межпроцессного взоимодействия
- •4.5 Механизмы межпроцессорного взаимодействия
- •4.5.1 Очереди сообщений
- •4.5.2 Семафоры Семафоры как теоретическая конструкция
- •4.5.3 Разделяемая память
- •4.5.4 Потоки
- •Int pthread_setschedparam(pthread_t tid, int policy, const struct sched_param *param);
- •Int pthread_getschedparam(pthread_t tid, int policy, struct schedparam *param);
- •5 Операционные системы
- •5.1 Понятие операционной системы
- •5.2 Характеристики современных ос
- •5.2.1 Многопоточность
- •5.2.2 Распределенные ос
- •5.2.3 Концепция ос на основе микроядра
- •5.2.4 Функции микроядра.
- •5.3 Принципы построения ос
- •5.4 Концептуальные основы ос
- •5.4.1 Процессы
- •Модель работы процесса с двумя приостановочными состояниями
- •Варианты решения:
- •Решение задачи взаимного исключения. Алгоритм Деккера.
- •Решение задачи взаимного исключения. Алгоритм Пэтерсона..
- •Синхронизирующие примитивы (семафоры).
- •Задача “производитель-потребитель” Общие семафоры
- •Задача “производитель-потребитель”, буфер неограниченного размера(Спящий парикмахер)
- •Задача “производитель-потребитель”, буфер ограниченного размера
- •5.4.2 Распределение ресурсов. Проблема тупиков
- •Алгоритм банкира
- •Применение алгоритма банкира
- •5.4.3 Монитороподобные средства синхронизации
- •Механизм типа «критическая область»
- •5.4.4 Виртуализация
- •5.4.5 Подсистема управления памятью
- •5.4.6 Виртуальная оперативная память
- •5.5 Аппаратные особенности процессоров Intel-архитектуры, направленных на поддержку многозадачности
- •5.5.1 Сегментация памяти. Ia-32
- •5.5.2 Распределение памяти в реальном режиме
- •5.5.3 Организация защиты в процессоре
- •5.5.4 Поддержка многозадачности в процессорах архитектуры ia-32
1.7 Аргументы и опции программы
Каждая программа обрабатывает переданные ей аргументы в соответствии со своим алгоритмом работы. Для унифицирования интерфейса передачи аргументов используется механизм опций.
Прототипы головной функции (по стандарту):
int main (int argc, char ** argv, char ** envp)
int main (int argc, char ** argv)
Запуск программы:
>prog1 PAR1 PAR2 PAR3 <Enter>
argc = 4
argv[0] = “prog1”
argv[1] = “PAR1”
argv[2] = “PAR2”
argv[3] = “PAR3”
argv[4] = NULL
Механизм опций позволяет разделить все элементы программы на следующие категории:
сама опция: -о; -е //обычно присутствует дефис
многосимвольные опции имеют два дефиса: --Lim
зависимые аргументы
>gcc –o prog1.out prog1.c
предполагают наличие аргумента: -о <аргумент>
свободные аргументы
>gcc –o prog1.out prog1.c
не связаны напрямую с опциями
Функция обработки коротких опций:
#include <getopt.h>
int getopt (int argc, char ** argv, const char * opts);
Первые два аргумента – аргументы функции main, которые получает программа. Третий аргумент – строка, которая является перечнем опций, используемых программой (без разделений и дефисов). Если после имени опции стоит : ,то следующая опция является зависимым аргументом.
Пример: ab:c
Используемые опции:
-a
-b, которая требует –с.
Обработка опций программы подразумевает неоднократный вызов функции getopt, которая возвращает код очередного фактического аргумента. Если пользователь ввел опцию, которая не указана в перечне, то возвращается ?, если все опции уже обработаны – функция возвращает -1
#include <stdio.h>
#include <getopt.h>
int main (int argc, char ** argv) {
FILE * outfile = stdout;
int i, opt;
char * filename = NULL;
char help_str[] = {“/формат вызова: getoptdemo[OPT] ARGS\n”,
“-h -вызов помощи\n”,
“-o <outfile> -запись в файл \n”};
while ( (opt = getopt (argc, argv, “ho:”)) != 1 ) {
switch (opt) {
case ‘h’: printf(“%s”, help_str); return (0);
case ‘o’: filename = optarg; break;
case ‘?’: printf(“%s”, help_str); return (0);
default: printf(“Неизвестная ошибка\n”); return(1);
}
}
if (optind >= argc) {
printf (“Нет аргумента\n”);
return (1);
}
if (filename != NULL) {
outfile = fopen (filename, “w”);
if (outfile == NULL) {
printf (“файл не открыт\n”);
return (-1);
}
}
for (i=optind; i<argc; i++)
fprintf (outfile, “%s\n”, argv[i]);
if (outfile != stdout)
fclose(outfile);
return (0);
}
1.8 Обработка ошибок
Обработке ошибок уделяется большое значение в UNIX, так как написание надежных и устойчивых программ, особенно для многопользовательских систем, является весьма важным.
Обычно в случае возникновения ошибки системные вызовы возвращают -1 и устанавливают значение переменной errno, указывающее возникновение ошибки. Библиотечные функции, как правило, значение errno не устанавливают, а код возврата различен для различных функций. Переменная errno не обнуляется следующим нормально завершившимся системным вызовом, следовательно эту переменную следует анализировать сразу же после системного вызова, который завершился с ошибкой.
Имеются также две функции, помогающие сообщить причину ошибочной ситуации.
external int errno;
#include <string.h>
char *strerror (int enum);
#include <errno.h>
#include <stdio.h>
void perror (char *s);
main (int argc, char *argv[ ])
{
fprintf(stderr, “ENOMEM:%s\n”, strerror (ENOMEM));
errno = ENOEXEC;
perror (argv[0]);
}
Функция strerror принимает в качестве аргумента номер ошибки и возвращает указатель на строку, содержащую сообщение о причине ошибочной ситуации.
Функция perror выводит в стандартный поток сообщений об ошибках информацию об ошибочной ситуации, основываясь на значении переменной errno. Строка s, передаваемая функции в качестве аргумента, предваряет сообщение об ошибке и может содержать дополнительную информацию, например название функции, в которой произошла ошибка.
Имеется условное обозначение большого числа ошибочных ситуаций, при которых они могут обнаруживаться и обрабатываться. Некоторые из них приведены ниже.
№ |
Ошибочная ситуация |
Примечание |
1 |
E2BIG |
Размер списка аргументов, переданных системному вызову exec плюс размер экспортируемых переменных окружения превышает максимально допустимое число байт (ARG_MAX). |
2 |
EACCESS |
Попытка доступа к файлу с недостаточными правами доступа для данного класса. |
3 |
EAGAIN |
Превышен предел использования некоторого ресурса, например переполнена таблица процессов. |
4 |
EBADF |
Попытка операции с файловым дескриптором, не адресующим никакой файл или попытка работы с файлом на недопустимую операцию (например, файл открыт на чтение, а попытка записи). |
5 |
EBADFD |
Файловый дескриптор не адресует открытый файл или попытка выполнения операции чтения с файловым дескриптором, полученным при открытии только на запись. |
6 |
EBUSY |
Попытка монтирования устройства (файловой системы), которое уже примонтировано; попытка размонтировать файловую систему, имеющую открытые файлы; попытка обращения к недоступным ресурсам. |
7 |
ECHILD |
Вызов функции wait процессом, не имеющим дочерних процессов или повторный вызов wait для процесса, для которого этот вызов уже был сделан. |
8 |
EDQUOT |
Зарезервирован |
9 |
EEXIST |
Имя существующего файла использовано в недопустимом контексте, например, попытка создания символической связи с именем уже существующего файла. |
10 |
EFAULT |
Аппаратная ошибка при попытке использования системой аргумента функции, например, в качестве указателя передан недопустимый адрес. |
11 |
EFBIG |
Размер файла превысил установленное ограничение RLIMIT_FSIZE или максимально допустимый размер для данной файловой системы. |
12 |
EINTR |
Получение асинхронного сигнала (SIGINT или SIGQUIT) во время обработки системного вызова.Если выполнение процесса будет продолжено после обработки сигнала, прерванный системный вызов завершится с этой ошибкой. |
13 |
EINVAL |
Передача неверного аргумента системному вызову. |
14 |
EIO |
Ошибка ввода-вывода физического устройства. |
15 |
EISDIR |
Попытка операции, недопустимой для каталогов. |
16 |
EMFILE |
Число открытых файлов для процесса превысило максимально допустимое значение. |
17 |
ENAMETOOLONG |
Длина имени файла, включая путь, превысило максимально допустимое значение. |
18 |
ENFILE |
Переполнение файловой таблицы. |
19 |
ENODEV |
Попытка недопустимой операции для устройства. |
20 |
ENOENT |
Файл с указанным именем не существует или отсутствует каталог, указанным в полном имени файла . |
21 |
ENOEXEC |
Попытка запуска на выполнение файла, который имеет права на выполнение, но не является файлом допустимого исполняемого формата |
22 |
ENOMEM |
Размер запрашиваемой памяти при запуске программы превысил максимально возможный в системе. |
23 |
ENOTDIR |
При задании имени каталога в операции, предусматривающей в качестве аргумента имя каталога, было указано имя файла другого типа. |
24 |
EPIPE |
Попытка записи в канал, для которого не существует процесса, принимающего данные. В этой ситуации процессу обычно направляется сигнал, ошибка возвращается при игнорировании сигнала. |
25 |
ESRCH |
Процесс с указанным PID не существует. |
Программистам также предоставляется большой набор функций общего назначения, которые не являются точками входа в операционную систему, хотя в процессе выполнения многие из них выполняют системные вызовы (например, функция printf записывает данные в файл, используя системный вызов read). Библиотечные функции, хранящиеся в стандартных библиотеках вместе с системными вызовами, составляют основу среды программирования UNIX.
При разработке программ важное значение имеют файлы заголовков, где описаны значения большого количества констант и т.д.