- •Кафедра программного обеспечения информационных технологий
- •«Операционные системы и системное программирование»
- •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
2.6 Мультиплексированный ввод/вывод
Мультиплексированный ввод/вывод позволяет программе одновременно фиксироваться на нескольких файловых дескрипторах и получать уведомления, когда один или несколько из них становятся доступными для чтения или для записи без блокировки.
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
Системный вызов select позволяет получить информацию о состоянии файловых дескрипторов, используя тип fd_set, который определяет набор файловых дескрипторов. В системном вызове в качестве параметров указаны три параметра данного типа (а именно набор файловых дескрипторов, в которых ожидается момент доступности для чтения, readfds, или для записи, writefds, для сокетов – определяется исключительная ситуация, exceptfds). Первый параметр определяет значение файлового дескриптора, который на единицу больше, чем максимальное значение файлового дескриптора, состояние которого будет анализироваться. Последний параметр определяет время для анализа ситуации по файловым дескрипторам, если указатель NULL, то системный вызов сразу же возвратит значение, если же явно задано время в секундах и микросекундах, то на протяжении этого времени анализируется ситуация, после чего выдается значение. Структура, которая представляет время следующая:
struct timeval
{ long tv_sec;
long tv_usec; }
Имеются специальные макросы для работы с наборами файловых дескрипторов:
FD_CLR(int fd, fd_set *set);
FD_ISSET(int fd, fd_set *set);
FD_SET(int fd, fd_set *set);
FD_ZERO(fd_set *set);
Первый макрос устанавливает 0 в значение файлового дескриптора fd из заданного набора дескрипторов, второй – проверяет, включен ли файловый дескриптор в набор, третий – добавляет в набор файловый дескриптор, а четвертый – обнуляет набор файловых дескрипторов.
При успешном завершении возвращается число файловых дескрипторов во всех трех наборах, готовых к вводу/выводу. Также может быть возвращено значение 0. Такая ситуация может произойти, когда время истекло, а файловые дескрипторы не выявлены.
При ошибке возвращается -1 и переменная errno принимает одно из следующих значений:
EBADF – в одном из наборов содержится недопустимый дескриптор
EINTR – во время ожидания был получен сигнал
EINVAL – указанное значение тайм-аута недопустимо
ENOMEM – недостаточно памяти для выполнения запроса
Надо помнить также то, что перед запуском наборы файловых дескрипторов должны получить свои значения.
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#define TIMEOUT 2
#define BUF_LEN 1024
int main(void) {
struct timeval tv;
fd_set readfds;
int ret;
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
tv.tv_sec=TIMEOUT;
tv.tv_usec=0;
ret=select(STDIN_FILENO+1, &readfds, NULL, NULL, &tv);
// проверяем можно ли читать с ввода/вывода
if (ret==-1)
{ perror(“select”);
return(1); }
else if (!ret)
{printf(“%d секунд прошли\n”, TIMEOUT;
return(0); }
if (FD_ISSET(STDIN_FILENO,&readfds))
// проверяем для ожидаемого файлового дескриптора
{ char buf[BUF_LEN+1];
int len;
len=read(STDIN_FILENO, buf, BUF_LEN);
if (len==-1)
{ perror(“read”);
return(1); }
if (len)
{ buf[len]=’\0’;
printf(“read: %s\n”, buf); }
return(0); }
else printf(“Такое невероятно !\n”);
return (1);
}
Принцип системного вызова select можно использовать для засыпания программы на время <1с. К примеру, select(0, NULL, NULL, NULL, &tv).
Следующий системный вызов проверяет файловые дескрипторы и права доступа (возможность работы). Файловые дескрипторы находятся в массиве, который определен первым параметром вызова.
#include <sys/poll.h>
int poll(struct pollfd *fds, unsigned int nfds,int timeout);
Каждый элемент определяет такую структуру: первый элемент – номер дескриптора, второй – какие события должны наблюдаться для этого файла, третий же параметр – события, какие реально присущи файлу.
struct pollfd
{ int fd;
short events;
short revents; }
Поля events, revents определены битовыми масками:
POLLIN – есть данные для чтения
POLLRDNORM – есть обычные данные для чтения
POLLRDBAND – есть приоритетные данные для чтения
POLLPRI – есть срочные данные для чтения
POLLOUT – операция записи не заблокируется
POLLWRNORM – операция записи обычных данных не заблокируется
POLLWRBAND – запись приоритетных данных не заблокируется
POLLMSG –доступно сообщение SIGPOLL
В качестве возвращаемых событий:
POLLER – ошибка в указанном дескрипторах
POLLHUR – зависшее событие для данного дескриптора
POLLNVAL – дескриптор файла не допустим
Третий параметр определяет длину, ожидающую в миллисекундах (мс), когда интервал времени истекает, вызов возвращает значение, даже если дескриптор к вводу/выводу не обнаружены. Если этот параметр равен 0, то вызов возвращает значение немедленно.
Второй параметр – это сколько элементов массива наблюдается.
При успешном завершении системный вызов возвращается число дескрипторов, у которых revents не равно 0. Если их нет return(0) при ошибке – (-1). Ошибочные ситуации, значения которых заносятся в ERRNO:
EBADF – недопустимый дескриптор файла
EFAULT – указывается на fds, находящиеся за пределами адресного пространства
EINTR – получен сигнал до истечения времени
EINVAL – второй параметр больше чем значение
ENOMEN – нехватка памяти для выполнения запроса
Пример, который показывает работу системного вызова poll:
#include <sys/poll.h>
#include <stdio.h>
#include <unistd.h>
#define TIMEOUT 2
int main(void)
{
struct pollfd fds[2];
int ret;
fds[0].fd=STDIN_FILENO;
fds[0].events=POLLIN;
fds[1].fd=STDOUT_FILENO;
fds[1].events=POLLOUT;
// задание файловых дескрипторов и событий, которые ожидаются
ret=poll(fds, 2, TIMEOUT*1000);
// проверяются файловые дескрипторы, которые заданы
if (ret==-1)
{ perror(“poll”);
return(1); }
if (!ret)
{ printf(“%d секунд истекли\n”,TIMEOUT);
return(0); }
if (fds[0].revents & POLLIN)
{ printf(“stdin доступен на чтение \n”); }
if (fds[1].revents & POLLOUT)
{ printf(“stdout доступен для записи \n”); }
return(0);
}