Главная » Просмотр файлов » Вордовские лекции

Вордовские лекции (1115151), страница 10

Файл №1115151 Вордовские лекции (Вордовские лекции) 10 страницаВордовские лекции (1115151) страница 102019-05-08СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 10)

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

Рассмотрим второе определение процесса Unix.

Предварительно определим понятие системный вызов. Системный вызов – специальная функция, позволяющая процессу обращаться к ядру ОС за выполнением тех или иных действий. Это может быть запрос на выполнение операций обмена, управления процессами, получения системной информации и т.п. При выполнении системного вызова в процессе происходит инициация специального прерывания «обращение к системе» . В разных системах детали реализации системного вызова могут отличаться друг от друга и название прерывания «обращение к системе» здесь выбрано достаточно условно. В любом случае использование системного вызова влечет за собой накладные расходы, связанные со сменой контекста выполняющегося в данный момент процесса.

Если системный вызов не выполняется или выполняется нештатно, то он возвращает –1 в коде ответа и в переменной errno будет находится код причины отказа (для диагностирования результатов выполнения системного вызова в процессе используется переменная errno, объявленная в файле errno.h).

Процесс в ОС Unix – это объект, порожденный системным вызовом fork(). Данный системный вызов является единственным стандартным средством порождения процессов в системе Unix. Ниже рассмотрим возможности данного системного вызова подробнее.

6.1.2Базовые средства организации и управления процессами

Для порождения новых процессов в UNIX существует единая схема, с помощью которой создаются все процессы, существующие в работающем экземпляре ОС UNIX, за исключением первых двух процессов (0-го и 1-го)1.

Для создания нового процесса в операционной системе UNIX используется системный вызов fork(), в результате в таблицу процессов заносится новая запись, и порожденный процесс получает свой уникальный идентификатор. Для нового процесса создается контекст, большая часть содержимого которого идентична контексту родительского процесса, в частности, тело порожденного процесса содержит копии сегментов кода и данных его родителя. Сыновний процесс наследует от родительского процесса:

  • окружение - при формировании процесса ему передается некоторый набор параметров-переменных, используя которые, процесс может взаимодействовать с операционным окружением (интерпретатором команд и т.д.);

  • файлы, открытые в процессе-отце, за исключением тех, которым было запрещено передаваться процессам-потомкам с помощью задания специального параметра при открытии. (Речь идет о том, что в системе при открытии файла с файлом ассоциируется некоторый атрибут, который определяет правила передачи этого открытого файла сыновним процессам. По умолчанию открытые в «отце» файлы можно передавать «потомкам», но можно изменить значение этого параметра и блокировать передачу открытых в процессе-отце файлов.);

  • способы обработки сигналов;

  • разрешение переустановки эффективного идентификатора пользователя;

  • разделяемые ресурсы процесса-отца;

  • текущий рабочий каталог и домашний каталоги

  • и т.д.

По завершении системного вызова fork() каждый из процессов – родительский и порожденный – получив управление, продолжат выполнение с одной и той же инструкции одной и той же программы, а именно с той точки, где происходит возврат из системного вызова fork(). Вызов fork() в случае удачного завершения возвращает сыновнему процессу значение 0, а родительскому PID порожденного процесса. Это принципиально важно для различения сыновнего и родительского процессов, так как сегменты кода у них идентичны. Таким образом, у программиста имеется возможность разделить путь выполнения инструкций в этих процессах.

В случае неудачного завершения, т.е. если сыновний процесс не был порожден, системный вызов fork() возвращает –1, код ошибки устанавливается в переменной errno.

Рис. 2 Выполнение системного вызова fork()

Пример.

int main(int argc, char **argv)

{

printf("PID=%d; PPID=%d \n",getpid(),getppid());

/*печать PID текущего процесса и PID процесса-предка */

fork();

/*создание нового процесса, с этого момента два процесса функционируют параллельно и независимо*/

printf("PID=%d; PPID=%d \n",getpid(),getppid());

/*оба процесса печатают PID текущего процесса и PID процесса-предка*/

}

Пример.

Программа создает два процесса – процесс-предок распечатывает заглавные буквы, а процесс-потомок строчные.

int main(int argc, char **argv)

{

char ch, first, last;

int pid;

if((pid=fork())>0)

{

/*процесс-предок*/

first =’A’;

last =’Z’;

}

else

{

/*процесс-потомок*/

first =’a’;

last =’z’;

}

for (ch = first; ch <= last; ch++)

{

write(1,&ch,1);

}

_exit(0);

}

Механизм замены тела процесса.

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

Заметим, что выполнение “нового” тела происходит в рамках уже существующего процесса, т.е. после вызова exec() сохраняется идентификатор процесса, и идентификатор родительского процесса, таблица дескрипторов файлов, приоритет, и большая часть других атрибутов процесса. Фактически происходит замена сегмента кода и сегмента данных. Изменяются следующие атрибуты процесса:

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

  • эффективные идентификаторы владельца и группы могут измениться, если для новой выполняемой программы установлен s-бит

  • перед началом выполнения новой программы могут быть закрыты некоторые файлы, ранее открытые в процессе. Это касается тех файлов, для которых при помощи системного вызова fcntl() был установлен флаг close-on-exec. Соответствующие файловые дескрипторы будут помечены как свободные.

Рис. 3 Выполнение системного вызова exec()

Ниже представлены прототипы функций семейства exec():

#include <unistd.h>

int execl(const char *path, char *arg0,…);

int execlp(const char *file, char *arg0,…);

int execle(const char *path, char *arg0,…, const char **env);

int execv(const char *path, const char **arg);

int execvp(const char *file, const char **arg);

int execve(const char *path, const char **arg, const char **env);

Первый параметр во всех вызовах задает имя файла программы, подлежащей исполнению. Этот файл должен быть исполняемым файлом и пользователь-владелец процесса должен иметь право на исполнение данного файла. Для функций с суффиксом «p» в названии имя файла может быть кратким, при этом при поиске нужного файла будет использоваться переменная окружения PATH. Далее передаются аргументы командной строки для вновь запускаемой программы, которые отобразятся в ее массив argv – в виде списка аргументов переменной длины для функций с суффиксом «l» либо в виде вектора строк для функций с суффиксом «v». В любом случае, в списке аргументов должно присутствовать как минимум 2 аргумента: имя программы, которое отобразится в элемент argv[0], и значение NULL, завершающее список.

В функциях с суффиксом «e» имеется также дополнительный аргумент, описывающий переменные окружения для вновь запускаемой программы – это массив строк вида name=value, завершенный значением NULL.

Пример.

#include <unistd.h>

int main(int argc, char **argv)

{

/*тело программы*/

execl(“/bin/ls”,”ls”,”-l”,(char*)0);

/* или execlp(“ls”,”ls”, ”-l”,(char*)0);*/

printf(“это напечатается в случае неудачного обращения к предыдущей функции, к примеру, если не был найден файл ls \n”);

}

В данном случае второй параметр – вектор из указателей на параметры строки, которые будут переданы в вызываемую программу. Как и ранее первый указатель – имя программы, последний – нулевой указатель. Эти вызовы удобны, когда заранее неизвестно число аргументов вызываемой программы.

Пример.

Вызов программы компиляции.

int main(int argc, char **argv)

{

char *pv[]={

“cc”,

“-o”,

“ter”,

“ter.c”,

(char*)0

};

/*тело программы*/

execv (“/bin/cc”,pv);

}

Чрезвычайно полезным является использование fork() совместно с системным вызовом exec(). Как отмечалось выше системный вызов exec() используется для запуска исполняемого файла в рамках существующего процесса. Ниже приведена общая схема использования связки fork() - exec().

Рис. 4 Использование схемы fork()-exec()

Пример. Использование схемы fork-exec

Программа порождает три процесса, каждый из которых запускает программу echo посредством системного вызова exec(). Данный пример демонстрирует важность проверки успешного завершения системного вызова exec() , в противном случае возможно исполнение нескольких копий исходной программы. В нашем случае если все вызовы exec() проработают неуспешно, то копий программ будет восемь. Если все вызовы exec() будут успешными, то после последнего вызова fork() будет существовать четыре копии процесса. В каком порядке они пойдут на выполнение предсказать трудно.

int main(int argc, char **argv)

{

if(fork()==0)

{

execl(“/bin/echo”,”echo”,”это”,”сообщение один”,NULL);

printf(“ошибка”);

}

if(fork()==0)

{

execl(“/bin/echo”,”echo”,”это”,”сообщение два”,NULL);

printf(“ошибка”);

}

if(fork()==0)

{

execl(“/bin/echo”,”echo”,”это”,”сообщение три”,NULL);

printf(“ошибка”);

}

printf(“процесс-предок закончился”)

}

Результат работы может быть следующим:

процесс-предок закончился

это сообщение три

это сообщение два

это сообщение один


Завершение процесса.

Для завершения выполнения процесса предназначен системный вызов _exit()

void _exit(int exitcode);

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

Кроме обращения к вызову _exit(), другими причинами завершения процесса могут быть:

  • оператора return, входящего в состав функции main()

  • получение некоторых сигналов (об этом речь пойдет чуть ниже)

В любом из этих случаев происходит следующее:

  • освобождаются сегмент кода и сегмент данных процесса

  • закрываются все открытые дескрипторы файлов

  • если у процесса имеются потомки, их предком назначается процесс с идентификатором 1

  • освобождается большая часть контекста процесса, однако сохраняется запись в таблице процессов и та часть контекста, в которой хранится статус завершения процесса и статистика его выполнения

  • процессу-предку завершаемого процесса посылается сигнал SIGCHLD

Состояние, в которое при этом переходит завершаемый процесс, в литературе часто называют состоянием “зомби”.

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

Характеристики

Тип файла
Документ
Размер
2,83 Mb
Тип материала
Высшее учебное заведение

Список файлов лекций

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6367
Авторов
на СтудИзбе
309
Средний доход
с одного платного файла
Обучение Подробнее