Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСиСП теория 4 семестра - методичка слайдов Бранцевич Петр Юльянович 2009.doc
Скачиваний:
160
Добавлен:
15.06.2014
Размер:
1.75 Mб
Скачать

3.8 Системный вызов system

#include <stdlib.h>

int system (const char * comand);

Позволяет выполнить заданную инструкцию в командном интерепретаторе. Это действие можно рассматривать как запуск процесса и ожидание его завершения. Дейтвие функции равносильно действию строки:

/bin/sh –c comand

Можно реализовать это действие, не используя функцию system:

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/wait.h>

int my_system (const char * cmd) {

int status;

pid_t pid;

pid = fork();

if (pid == -1) exit(-1);

else

if (pid == 0) {

const char * argv[4];

argv[0] = “sh”;

argv[1] = “-c”;

argv[2] = “cmd”;

argv[3] = “NULL”;

execv (“/bin/sh”,argv);

exit (-1);

}

if (waitpid (pid, &status, 0) == -1) exit (-1);

else

if (WIFEXITED(status)) exit(WEXITSTATUS(status));

exit (0);

}

В отличие от system здесь не блокируются никакие сигналы.

3.9 Основные параметры, передаваемые процессу

  1. идентификатор самого процесса и идентификатор родительского процесса.

  2. идентификатор пользователя и группы (владение процессом). Имеется понятие реального и действительного (эффективного) идентификаторов для пользователя и группы. Под реальным понимается идентификатор, который запускал процесс, а под действительным (эффективным) – идентификатор пользователя, который использовался при проверке прав доступа процесса к ресурсу.

В большинстве случаев реальный и эффективный идентификаторы – это одно и то же.

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

#include <unistd.h>

#include <sys/types.h>

uid_t geteuid(void); // эффективный

gid_t getegid(void); // эффективный

uid_t getuid(void); // реальный

gid_t getgid(void); // реальный

  1. Сеанс пользователей – показывает, кто из пользователей подключен к системе и работает с процессом.

3.10 Сеансы и группы процессов

Каждый процесс входит в состав какой-либо группы процессов (одной или нескольких). Принадлежность к группе позволяет организовать более плотное взаимодействие между процессами. Один процесс может послать сигнал всем процессам, входящим в определенную группу. Каждая группа имеет идентификато группы (Process group ID). Идентификатор группы – это идентификатор процесса, являющегося лидером этой группы.

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

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

Группа, которая является обязательной для сеанса называется приоритетной группой. Когда пользователь выходит из сеанса (отключается от терминала) всем процессам приоритетной группы отправляется сигнал SIGQUIT. Если пользователь нажимает Ctrl+C, всем процессам приоритетной группы посылается SIGINT.

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

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

#include <unistd.h>

pid_t getsid (pid_t pid);

pid_t setsid (void);

pid_t getpgid (pid_t pid);

int setpgid (pid_t pid, pid_t gpid);

  1. возвращает идентификатор сеанса для процесса, указанного в качестве аргумента. Если в качестве аргумента указан 0, то возвращает идентификатор сеанса, вызвавшего процесс

  2. создает новый сеанс, вызываемый процесс не должен быть лидером какой-либо группы процессов, т.к. в результате выполнения он становится лидером созданного сеанса, единственным процессом в этом сеансе, причем у этого процесса (а соответственно и у сеанса) не будет управляющего устройства. Этот системный вызов также создает новую группу процессов и вызывающий процесс становится лидером этой новой группы. При успешном завершении возвращается идентификатор созданного сеанса, при ошибке -1

  3. возвращает идентификатор группы для процесса, указанного в качестве аргумента. Если в качестве аргумента указан 0, то возвращает идентификатор группы для текушего процесса

  4. заносит процесс, заданный идентификатором (первым аргументом), в группу, идентификатор которой задан вторым аргументом. Если pid=0, то используется идентификатор вызывающего процесса. Если pid и pgid равны, то процесс становится лидером группы. Если pgid=0, то в качестве идентификатора группы используется значение pid. в случае ошибки функция возвращает -1.

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

int chroot (const char * path);

при успешном завершении вызова, если в программе указать путь «./», поиск начнется с заданного пути.

Также в качестве атрибутов есть приоритет процесса. Значение приоритета находится в диапазоне от -20 до +19. ОС планирует выполнение процессов с учетом их приоритетов. Изменить текущий приоритет процесса можно при помощи вызова:

#include <unistd.h>

int nice (int i);

Число i указывает, на сколько необходимо изменить текущий приоритет: т.е. если i=-5, то уменьшить на пять, если i=4, то увеличить на четыре. Вызов возвращает измененное значение приоритета.

Только системные процессы могут уменьшать приоритет.

#include <sys/types.h>

#include <sys/stat.h>

#include <stdlib.h>

#include <fentl.h>

#include <unistd.h>

#include <linux/fs.h>

int main () {

pid_t pid;

int I;

pid = fork();

if (pid == -1) exit (-1);

else if (pid != 0) exit (EXIT_SUCSESS);

if (setsid() == -1) exit (-1);

if (chdir(“/”) == -1) exit (-1);

for (i=0; i<NR_OPEN; i++) close (i);

open (“/dev/null”, O_RDWR); dup(0); dup(0);

// действия процесса

exit (-1);

}

Процессы демоны – это процессы, которые выполняются в фоновом режиме. Они не подключены ни к одному из терминалов. Они обычно запускаются во время загрузки системы от имени суперпользователя или другого специального пользователя. В основном они предназначены для решения системных вопросов. К процессам-демонам предъявляются 2 требования:

- они должны выполняться как потомки процесса инициализатора

- они не должны быть связаны с терминалом

Для создания процесса-демона необходимо:

  1. выполнить вызов fork

  2. в родительском процессе выполнить exit

  3. выполнить системный вызов setsid, создав тем самым новый сеанс, новую группу процессов. Тем самым и в сеансе и в группе лидером становится созданный процесс. Это гарантирует, что процесс не связан с терминалом

  4. рабочий каталог меняется на корневой для того, чтобы вызывающиеся процессы могли работать с любыми каталогами

  5. закрыть все открытые файлы

  6. открыть стандартные дескрипторы ввода/вывода и сообщения об ошибках и перенаправить вывод на 0-е устройство