- •Билеты по 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
Сигналы. Наследование сигналов. Задание обработчика сигнала.
Сигнал является способом передачи уведомления о некотором произо
шедшем событии между процессами или между ядром системы и процес
сами. Сигналы можно рассматривать, как простейшую форму межпро
цессного взаимодействия, хотя на самом деле они больше напоминают
программные прерывания, при которых нарушается нормальное выполне
ние процесса. Сигнал может быть отправлен процессу либо ядром, либо другим процес
сом с помощью системного вызова int kill(pid_t pid, int sig).
С помощью системного вызова kill(2) процесс может послать сигнал как
самому себе, так и другому процессу или группе процессов. В этом случае
процесс, посылающий сигнал, должен иметь те же реальный и эффективный идентификаторы, что и процесс, которому сигнал отправляется. Разумеется, данное ограничение не распространяется на процессы, обладаю
щие привилегиями суперпользователя. Такие процессы имеют возможность отправлять сигналы любым процессам системы. Процесс может выбрать одно из
трех возможных действий при получении сигнала:
П игнорировать сигнал,
П перехватить и самостоятельно обработать
П позволить действие по умолчанию. Сигналы SIGKILL и SIGSTOP невозможно ни игнорировать, ни перехватить. При получении сигнала в большинстве
случаев по умолчанию происходит завершение выполнения процесса. В
случаев в текущем рабочем каталоге процесса также создается файл
core , в котором
хранится образ памяти процесса. Этот файл может быть впоследствии про
анализирован программой отладчиком для
состояния процес
са непосредственно перед завершением. Файл core не будет создан в сле
случаях:
1) исполняемый файл процесса имеет установленный бит
SUID и реальный владелец пользователь процесса не является владельцем
пользователем исполняемого файла;
2) исполняемый файл процесса имеет установленный бит SGID, и реальный владелец группа процесса не является владельцем группой
исполняемого файла;
3) процесс не имеет права записи в текущем рабочем каталоге;
4) размер файла core слишком велик (превышает допустимый предел RLIMIT_CORE)
Обработчик сигнала.
Функция обработчика сигнала будет вызвана по сигналу, сигнал будет подан в качестве
параметра.
Один обработчик может обрабатывать несколько сигналов. Чтобы задать обработчик
используем функцию *signal. В результате выполнения этой функции получится
указатель на функцию с целым параметром который возвращает void. (т.е. чтобы
получить тип войд надо взять указатель на то что возвращает функция с параметрами (int
sig, void (*func) (int))) (int);). Все эти функции возвращают обработчик сигнала. Т.е. два
параметра: 1) номер сигнала, 2) функция, которая должна быть обработчиком сигнала.
SIG_IGN & SIG_DFL. Если первое - сигнал игнорируется. Если функция-сигнал
возвращает второе, значит обработчик стоял по умолчанию(не был задан).
Что происходит с обработчиками сигнала при создании нового процесса? Обработчики сигналов копируются. Что происходит с обработчиками сигналов по системному вызову
exec? Все обработчики сигналов, которые были у процесса перестали существовать.
Таким образом, все обработчики сигналов возвращаются в дефолтное состояние,
кроме(!) игнорирования сигналов.
Большинство программ в Юниксе, в которых задается обработчик сигналов, обработчик сигналов не устанавливается, если сигнал игнорируется. т.е. большинство программ
сначала проверяют не игнорируется ли этот сигнал. как это можно написать?
if (signal(n, SIG_IGN)!=SIG_IGN) signal(n, myfunc);
Если придет несколько сигналов, будет вызван только 1 обработчик. Сигналы могут быть
утеряны.
Все системные вызовы делятся на два типа: быстрые и медленные. Быстрые - выполнятся за конечное время(чтение с диска, запрос текущего времени). Медленные - чтение с клавиатуры. Если медленный, то системный вызов прекратит работу и вызовет обработчик. В errno EINTR.
Что может и не может делать обработчик сигнала?
Допустим, у нас есть ф-ция main, в которой объявлены глобальные переменные.
int var
main()
{
signal(n, func);
var=5;
var++;
if(var==6)
{...................................}
func (int n)
{
var++;
}
Глобальные переменные можно менять ИЛИ только в обработчике сигнала, ИЛИ в
основной программе. Иначе поведение программы будет всегда различно.
Если есть какая-то функция, в которой используются или статическая или глобальная переменные, которые используются и там, и там. Программа будет вести себя очень
хаотично.
Пример программы, где есть статическая(глобальная) переменyая, которая используется
и там, и там: malloc. Может вызываться ЛИБО из обработчика сигнала, или из основной
программы. Любая функция, которая внутри себя использует malloc - аналогично. Пример:
printf. такие функции называются реентерабильными(которые можно вызвать из
обработчика сигнала).
Если функция вызывает сама себя, значит прерывание работы программы может в особых местах. Реентерабильной программы - в любом месте. Чтобы быть реент. нужно,
чтобы не использовались статические и глобальные переменные, все данные должны
умещаться в стеке. У некоторых функций могут быть реентерабильные варианты, даже
если они сами не являются таковыми. Например, для ctime есть ctime_r.
Сигнал SIGALRM
alarm - это будильник. Параметр - число секунд, через которое надо разбудить
процесс(через которое процесс получит SIGALRM)
Чтение директорий из программы на языке C. Функции opedir, readdir, closedir. Функции stat, lstat, fstat. Чтение директорий из программы Си:
1) Получение списка файлов в каталоге 2) Получение информации о файле из его инода #include <sys/types.h> #include <dirent.h>
DIR *opendir(char *name);
Функция opendir служит для открытия потока информации для директории, имя которой расположено по указателю name. Тип данных DIR представляет собой некоторую структуру данных, описывающую такой поток. Функция opendir подготавливает почву для функционирования других функций, выполняющих операции над директорией, и позиционирует поток на первой записи директории.
При удачном завершении функция возвращает указатель на открытый поток директории, который будет в дальнейшем передаваться в качестве параметра всем другим функциям, работающим с этой директорией. При неудачном завершении возвращается значение NULL.
#include <sys/types.h> #include <dirent.h>
struct dirent *readdir(DIR *dir);
Описание функции
Функция readdir служит для чтения очередной записи из потока информации для директории.
Параметр dir представляет собой указатель на структуру, описывающую поток директории, который вернула функция opendir().
Тип данных struct dirent представляет собой некоторую структуру данных, описывающую одну запись в директории. Поля этой записи сильно варьируются от одной файловой системы к другой, но одно из полей, которое собственно и будет нас интересовать, всегда присутствует в ней. Это поле char d_name[ ] неопределенной длины, не превышающей значения NAME_MAX+1, которое содержит символьное имя файла, завершающееся символом конца строки. Данные, возвращаемые функцией readdir, переписываются при очередном вызове этой функции для того же самого потока директории.
При удачном завершении функция возвращает указатель на структуру, содержащую очередную запись директории. При неудачном завершении или при достижении конца директории возвращается значение NULL.
int closedir(DIR *dir);
Описание функции
Функция closedir служит для закрытия потока информации для директории, ассоциированного с указателем dir (т.е. с тем, что вернула функция opendir()). После закрытия поток директории становится недоступным для дальнейшего использования. При успешном завершении функция возвращает значение 0, при неудачном завершении - значение -1. #include <sys/stat.h> #include <unistd.h>
int stat(char *filename, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(char *filename, struct stat *buf);
Системные вызовы stat, fstat и lstat служат для получения информации об атрибутах файла. Системный вызов stat читает информацию об атрибутах файла, на чье имя указывает параметр filename, и заполняет ими структуру, расположенную по адресу buf. Заметим, что имя файла должно быть полным, либо строиться относительно той директории, которая является текущей для процесса, совершившего вызов. Если имя файла относится к файлу типа "связь", то читается информация (рекурсивно!) об атрибутах файла, на который указывает символическая связь. Системный вызов lstat идентичен системному вызову stat за одним исключением: если имя файла относится к файлу типа "связь", то читается информация о самом файле типа "связь". Системный вызов fstat идентичен системному вызову stat, только файл задается не именем, а своим файловым дескриптором (естественно, файл к этому моменту должен быть открыт). Для системных вызовов stat и lstat процессу не нужны никакие права доступа к указанному файлу, но могут понадобиться права для поиска во всех директориях, входящих в специфицированное имя файла. Структура stat в различных версиях UNIX может быть описана по-разному.
struct stat (man 2 stat)
st_ino - inod
st_nlink - число жестких ссылок
st_atime - время послед, дост к ф.
st_mtime - последняя модификация
st_ctime - когда менялся inode
st_size - размер файла
st_uid
st_gid
st_mode - 1) тип файлового объекта; 2) права доступа
Для определения типа файла можно использовать следующие логические макросы, применяя их к значению поля st_mode:
S_ISLNK(m) - файл типа "связь"? S_ISREG(m) - регулярный файл? S_ISDIR(m) - директория? S_ISCHR(m) - специальный файл символьного устройства? S_ISBLK(m) - специальный файл блочного устройства? S_ISFIFO(m) - файл типа FIFO? S_ISSOCK(m) - файл типа socket?
Младшие 9 бит поля st_mode определяют права доступа к файлу Системный вызов возвращает значение 0 при нормальном завершении и значение -1 при возникновении ошибки.
Использование функции flock для взаимной блокировки процессов. Виды файловых замков. Файловый замок — это запрет на доступ к файлу другим процессам одним процессом. События, связанные с навешиванием замков на файлы. Если процесс попытается
обратиться к файлу под замком, то перейдет в режим ожидания пока замок не будет снят. Можно вешать на доступные файлы замки (если файл закроется, то все замки автоматически снимаются:
1)shared
(разделяемый) — Позволяется вешать несколько замков разными процессами. 2) exclusive ( Исключающий) — Ждет, пока все shared будут сняты. Обычно shared для чтения, exclusive для записи. Системный вызов для вешания замков — flock ( int поток ввода-вывода, int тип замка) LOCK_SH — shared
LOCK_EX — exclusive LOCK_NB — если пытаются закрыть закрытый процесс, то выдает ошибку, не вставая в очередь LOCK_UN — снять замок
Чтение мягких ссылок с помощью системного вызова readlink. Системные вызовы link, symlink, readlink, unlink. #include <unistd.h>
int link(char *pathname, char *linkpathname); int symlink(char *pathname, char *linkpathname); int unlink(char *pathname); int readlink(const char *path, char *buf, size_t bufsiz);
Системный вызов link служит для создания жесткой связи к файлу с именем, на которое указывает параметр pathname. Указатель на имя создаваемой связи задается параметром linkpathname (полное или относительное имя связи).
Во всех существующих реализациях операционной системы UNIX запрещено создавать жесткие связи к директориям. Системный вызов symlink служит для создания символической (мягкой) связи к файлу с именем, на которое указывает параметр pathname. Указатель на имя создаваемой связи задается параметром linkpathname (полное или относительное имя связи).
Никакой проверки реального существования файла с именем pathname системный вызов не производит. Системный вызов unlink служит для удаления имени, на которое указывает параметр pathname, из файловой системы. Если после удаления имени счетчик числа жестких связей у данного файла стал равным 0, то возможны следующие ситуации:
Если в операционной системе нет процессов, держащих данный файл открытым, то файл полностью удаляется с физического носителя.
Если удаляемое имя было последней жесткой связью для регулярного файла, но какой-либо процесс держит его открытым, то файл продолжает существовать до тех пор, пока не будет закрыт последний файловый дескриптор, ссылающийся на данный файл.
Если имя относится к файлу типа socket, FIFO или к специальному файлу устройства, то файл удаляется независимо от наличия процессов, держащих его открытым, но процессы, открывшие данный объект, могут продолжать пользоваться им.
Если имя относится к файлу типа "связь", то он удаляется, и мягкая связь оказывается разорванной.
Все три системных вызова возвращают значение 0 при нормальном завершении и значение -1 при возникновении ошибки. readlink в буфер записывает значение мягкой ссылки(символической)
первый параметр - имя файла(ссылки)
2 - буфер
3 - длина буфера readlink не добавляет в buf символ NUL. Если файл, помещаемый в буфер, слишком мал, его длина bufsiz будет урезана.
