- •Билеты по unix.
- •Системные вызовы в Unix. Errno. Отличие системных вызовов от обычных функций. Обработка ошибок системных вызовов с помощью функций perror и strerror.
- •Завершение процессов. Отличие функции exit от системного вызова _exit. Функция atexit
- •Сигналы. Наследование сигналов. Задание обработчика сигнала.
- •Возвращаемые значения
- •Возвращаемое значение
- •Возвращаемое значение
- •Принцип согласования параметров
- •Запуск демонов через суперсервер inetd. Формат файла inetd.Conf. Файл /etc/services.
- •Параметры
- •Функции преобразования ip-адресов inet_ntoa(), inet_aton()
- •System V ipc. Типы объектов, используемых в System V ipc. Создание уникального ключа
- •Очереди сообщений. Функции msgget, msgsnd, msgrcv.
- •Семафоры. Функции semget и semop
Билеты по unix.
Системные вызовы в Unix. Errno. Отличие системных вызовов от обычных функций. Обработка ошибок системных вызовов с помощью функций perror и strerror.
Системный вызов — это обращение прикладной программы/функции к ядру операционной системы для выполнения какой-либо операции. Какие системные вызовы могут быть:
1)открыть файл (open, close) 2)записать пакет данных на диск ( read, write) 3)передать массив данных в сеть другому компьютеру. Errno — переменная целого типа. Каждый раз, когда системный вызов завершается ошибкой в эту переменную записывается код ошибки. Их всего 14. Если при системном вызове ошибок не было, то она остается без изменения. В современных ОС переменной errno нет, но есть такой макрос ( из-за многопоточности). Поэтому пишут #include <errno.h >.
perror и strerror — функции для печати ошибки на поле ошибок, которые соответствуют текущему знаению errno.
Strerror: параметр — целое число, значение переменной errno. Возвращаемое значение:
Указатель на строку, содержащую описание ошибки, код которой указан в аргументе errcode.
Функция strerror формирует описание ошибки по коду ошибки указанному в аргументе errcode и возвращает указатель на строку, содержащую сформированное описание ошибки. Функция ничего не возвращает. Функция выводи сообщение об ошибке в поток сообщений об ошибке. В начале выводится строка, на которую указывает аргумент функции, затем выводится двоеточие и пробел, затем выводится сообщение об ошибке, соответствующей значению errno. Если на момент вызова функции ошибок не зафиксировано или информация о них удалена, то в качестве сообщения об ошибке будет выведено сообщение: Success.
Создание процессов в Unix с помощью функции fork. Копирование при записи в виртуальную память. Прежде всего обрисуем общую схему возможностей пользователя, связанных с управлением процессами. Каждый процесс может образовать полностью идентичный подчиненный процесс с помощью системного вызова fork() и дожидаться окончания выполнения своих подчиненных процессов с помощью системного вызова wait. В заключение затронем еще одну важную тему, непосредственно связанную с управлением виртуальной памятью - копирование страниц при попытке записи (copy on write). При выполнении системного вызова fork() ОС UNIX образует процесс-потомок, являющийся полной копией своего предка. Тем не менее, у потомка своя собственная виртуальная память, и те сегменты, которые должны быть его частными сегментами, в принципе должны были бы полностью скопироваться. Однако, несмотря на то, что частные сегменты допускают доступ и по чтению, и по записи, ОС не знает, будет ли предок или потомок реально производить запись в каждую страницу таких сегментов. Поэтому было бы неразумно производить полное копирование частных сегментов во время выполнения системного вызова fork().
Поэтому в таких случаях используется техника копирования страниц при попытке записи. Несмотря на то, что в сегмент запись разрешена, для каждой его страницы устанавливается блокировка записи. Тем самым, во время попытки выполнения записи возникает прерывание по защите памяти, и ОС на основе анализа статуса соответствующего сегмента принимает решение о выделении новой страницы, копировании на нее содержимого оригинальной страницы и о включении этой новой страницы на место старой в виртуальную память либо процесса-предка, либо процесса-потомка (в зависимости от того, кто из них пытался писать). Чаще всего в потомке поcле системного вызова fork выполняется системный вызов exec, котоый замещает собой созд. Процесс. Описание Семейство функций exec... загружает и запускает другие программы, известные как "дочерние процессы. Если вызов функции exec... завершается успешно, "дочерний" процесс накладывается на "родительский" процесс; причем должно быть достаточно памяти для загрузки и выполнения "дочернего" процесса. pathname - это имя файла вызываемого "дочернего" процесса. Суффиксы l, v, p и e, добавляемые к имени семейства exec... обозначают, что данная функция будет работать с некоторыми особенностями:
p - определяет, что функция будет искать "дочернюю" программу в директориях, определяемых переменной PATH. Без суффикса p поиск будет производиться только в рабочем каталоге. Если параметр path не содержит маршрута, то поиск производится в текущей директории, а затем по маршрутaм, определяемым переменной окружения PATH.
l - показывает, что адресные указатели (arg0, arg1,..., argn) передаются, как отдельные аргументы. Обычно суффикс l употребляется, когда число передаваемых аргументов заранее вам известно.
v - показывает, что адресные указатели (arg[0], arg[1],...arg[n]) передаются, как массив указателей. Обычно, суффикс v используется, когда передаeтся переменное число аргументов.
e - показывает, что "дочернему" процессу может быть передан аргумент envp, который позволяет выбирать среду "дочернего" процесса. Без суффикса e "дочерний" процесс унаследует среду "родительского" процесса.
Каждая функция семейства exec... должна иметь один из двух суффиксов, определяющих аргументы (либо l, либо v). Суффиксы определения маршрута доступа (PATH) и унаследования операционной среды (p и e) являются необязательными.
Каждый элемент указывает на символьную строку с нулевым окончанием формы: envvar = value , где envvar - имя переменной среды, а value- значение символьной строки, которая присваивается каждой переменной envvar. Последним элементом в массиве envp[] является адресный нуль NULL. Когда значением envp[0] является NULL, "дочерний" процесс наследует назначения среды "родительского" процесса. При вызове функции exec... любые открытые файлы остаются открытыми и в "дочернем" процессе.
При успешном завершении функции exec... не возвра щают никакого значения. При возникновении ошибки функции exec... возвращают значение -1, а глобальная переменная errno получает значение. Вот что делает ядро системы при выполнении системного вызова fork:
Выделяет память под описатель нового процесса в таблице описателей процессов.
Назначает уникальный идентификатор процесса (PID) для вновь образованного процесса.
Образует логическую копию процесса, выполняющего системный вызов fork, включая полное копирование содержимого виртуальной памяти процесса-предка во вновь создаваемую виртуальную память, а также копирование составляющих ядерного статического и динамического контекстов процесса-предка.
Увеличивает счетчики открытия файлов (процесс-потомок автоматически наследует все открытые файлы своего родителя).
Возвращает вновь образованный идентификатор процесса в точку возврата из системного вызова в процессе-предке и возвращает значение 0 в точке возврата в процессе-потомке. exec позволяет в любой процесс загрузить новый иcполняемый код(т.е. заменить содержание ВП процеса) exec не создает новых процессов
Структура двоичных выполняемых файлов. Загрузка выполняемых файлов в текущий процесс. Статические и динамически библиотеки. Структура выполняемого файла
стр. 107 Робачевский
1 секция - секция кода(текста), машинные команды и константы
2 секция - секция данных: переменные, которым присвоены начальные значения инициализированные статические или внешние переменные
3 секция - bss. В выполняемом файле обычно только размер этой секции. В bss хранятся
неинициализированные данные , заполняются нулями при загрузке программы на выполнение. Необходимо хранить только размер и расположение в памяти для них.
4 секция - точки входа, размеры секций и другая служебная информация Загрузка выполняемых файлов в текущий процесс - 189 Роб. Пользователь, транслируя исходный текст программы, создает исполняемый файл, который состоит из нескольких частей:
- набора "заголовков", описывающих атрибуты файла,
- текста программы, - представления на машинном языке данных, имеющих начальные значения при запуске программы на выполнение, и указания на то, сколько пространства памяти ядро системы выделит под неинициализированные данные, так называемые bss (ядро устанавливает их в 0 в момент запуска),
- других секций, таких как информация символических таблиц. Ядро загружает исполняемый файл в память при выполнении системной операции exec, при этом загруженный процесс состоит по меньшей мере из трех частей, так называемых областей: текста, данных и стека. Области текста и данных корреспондируют с секциями текста и bss-данных исполняемого файла, а область стека создается автоматически и ее размер динамически устанавливается ядром системы во время выполнения. Стек состоит из логических записей активации, помещаемых в стек при вызове функции и выталкиваемых из стека при возврате управления в вызвавшую процедуру; специальный регистр, именуемый указателем вершины стека, показывает текущую глубину стека. Запись активации включает параметры передаваемые функции, ее локальные переменные, а также данные, необходимые для восстановления предыдущей записи активации, в том числе значения счетчика команд и указателя вершины стека в момент вызова функции. Текст программы включает последовательности команд, управляющие увеличением стека, а ядро системы выделяет, если нужно, место под стек. Поскольку процесс в системе UNIX может выполняться в двух режимах, режиме ядра или режиме задачи, он пользуется в каждом из этих режимов отдельным стеком. Стек задачи содержит аргументы, локальные переменные и другую информацию относительно функций, выполняемых в режиме задачи. Стек ядра содержит записи активации для функций, выполняющихся в режиме ядра. Элементы функций и данных в стеке ядра соответствуют функциям и данным, относящимся к ядру, но не к программе пользователя, тем не менее, конструкция стека ядра подобна конструкции стека задачи. Стек ядра для процесса пуст, если процесс выполняется в режиме задачи.
Каждому процессу соответствует точка входа в таблице процессов ядра, кроме того, каждому процессу выделяется часть оперативной памяти, отведенная под задачу пользователя. Таблица процессов включает в себя указатели на промежуточную таблицу областей процессов, точки входа в которую служат в качестве указателей на собственно таблицу областей. Областью называется непрерывная зона адресного пространства, выделяемая процессу для размещения текста, данных и стека. Точки входа в таблицу областей описывают атрибуты области, как например, хранятся ли в области текст программы или данные, закрытая ли эта область или же совместно используемая, и где конкретно в памяти размещается содержимое области. Внешний уровень косвенной адресации (через промежуточную таблицу областей, используемых процессами, к собственно таблице областей) позволяет независимым процессам совместно использовать области. Когда процесс запускает системную операцию exec, ядро системы выделяет области под ее текст, данные и стек, освобождая старые области, которые использовались процессом. Если процесс запускает операцию fork, ядро удваивает размер адресного пространства старого процесса, позволяя процессам совместно использовать области, когда это возможно, и, с другой стороны, производя физическое копирование. Если процесс запускает операцию exit, ядро освобождает области, которые использовались процессом.
Статические и динамически библиотеки.
Между стеком и кучей могут быть разделяемые библиотеки.
Статическая библиотека - это такая библиотека, которая связывается (линкуется) с программой в момент компиляции оной. При этом объектный код библиотеки помещается в исполняемый файл программы. С этой точки зрения статическая библиотека похожа на исходный код программы, с которой она связывается, за исключением того, что библиотека компилируется "кем-то еще" и программист, использующий библиотеку, имеет дело исключительно только с результатом этой компиляции.
Динамические библиотеки - выполняемые функции несколькими точками входа, каждая
соответствует своей функции.
инамическая библиотека - библиотека, подключаемая к программе в момент выполнения. Это означает, что при создании библиотеки производится не только ее компиляция, но и линковка с другими, нужными ей, библиотеками (!). Динамические библиотеки полезны в случаях, если: - Важно не перекомпилировать всю программу, а только перекомпилировать ту часть, которая реализует определенные функции - тогда эти функции выносятся в динамическую библиотеку; - Важно использовать в программах на C библиотеки, подготовленные на C++ и при этом избежать лишних трудностей с линковкой программы; - Кроме того, динамические библиотеки позволяют экономить место на жестком диске и в оперативной памяти, если одна и таже библиотека используется несколькими программами.
PIC - код, который не зависит от расположения в ВП.
Первый вызов из динамической библиотеки приводит к вызову динамического загрузчика.
Если страница уже есть, он ее отобразит. Если нет, то загружает и отображает.
Динамическое связывание выставляет правильный адрес функции, которую мы вызвали,
на то место, где она находится, чтобы не вызывать в другой раз загрузчик.
Обычно имеют расширение .so (shared object), располагается в /lib и /usr/lib
Преимущества и недостатки
Статические:
1) быстрее работают
2) большая переносимость
Динамические:
1) занимают меньше ВП
2) легче изменить поведение программы
При начале загрузки ОС большинство библиотек статические. Большинство программ
динамические.
