Вы на НеОфициальном сайте факультета ЭиП

На нашем портале ежедневно выкладываются материалы способные помочь студентам. Курсовые, шпаргалки, ответы и еще куча всего что может понадобиться в учебе!
Главная Контакты Карта сайта
 
Где мы?
» » » Операционные системы. Лабораторная работа

Реклама


Операционные системы. Лабораторная работа

Просмотров: 3039 Автор: admin
Лабораторная работа №2.1
Процессы.
Цель работы: изучить создание процессов в ОС Linux.
Методический материал.
Идентификаторы процессов.
Каждый процесс в Linux помечается уникальным идентификатором (PID , processidentifer).
Идентификаторы – это 16-разрядные числа, назначаемые последовательно помере создания процессов.
У всякого процесса имеется также родительский процесс (за исключениемспециального суперсервера init с идентификатором 1. Таким образом, всепроцессы Linux организованы в виде сложной иерархии, на вершине которойнаходится процесс init. Данное положение дел можно увидеть задав команду
ps -axf . К атрибутам процесса относится идентификатор его предка (PPID, parentprocess identifer).
Работая с идентификаторами процессов в программах, написанных на языках C иC++, следует объявить соответствующие переменные как имеющие тип pid_t(определяется в файле <sys/types.h>. Программа может узнать идентификаторсвоего собственного процесса с помощью системного вызова getpid(), аидентификатор своего родительского процесса с помощью системного вызоваgetppid(). Пример[1]:
#include<stdio.h>
#include<unistd.h>
int main()
{
printf ("Номер процесса: %d\n", (int) getpid() );
printf ("Номер родительского процесса: %d\n", (int) getppid());
return 0;
}
Обратите внимание на важную особенность: при каждом вызове программасообщает о разных идентификаторах, поскольку всякий раз запускается новыйпроцесс. Тем не менее, если программа вызывается из одного и того жеинтерпретатора команд, то родительский идентификатор оказываетсяодинаковым.
Создание процессов
Существуют два способа создания процессов. Первый из них относительно прост,применяется редко, поскольку неэффективен и связан со значительным рискомдля безопасности системы. Второй способ сложнее, но избавлен от недостатковпервого.Функция system()
Функция system() определена в стандартной библиотеке языка C и позволяетвызвать и программы системную команду, как если бы она была набрана вкомандной строке.
По сути, эта функция запускает стандартный интерпретатор и передает емукоманду на выполнение. Пример[2]:
#include<stdlib.h>
int main()
{
int return_value;
return_value = system("ls -l /");
return return_value;
}
  Функция system() возвращает код завершения указной команды. Еслиинтерпретатор не может быть запущен, возвращается значения 127, а в случаевозникновения других ошибок (-1). Поскольку функция system() запускает интерпретатор команд, она подверженавсем тем ограничениям безопасности, что и системный интерпретатор.Рассчитывать на наличие какой-то конкретной версии Bourne shell не приходится.В большинстве Unix-системах программа /bin/sh представляет собойсимволическую ссылку на другой интерпретатор в Linux это в основном bash.Вызов из функции system() программы с привилегиями пользователя root такжеможет иметь неодинаковые последствия в разных системах. Таким образом лучшесоздавать процессы с помощью функций fork() и exec().
Функции fork() и exec()
В DOS и Windows API имеется семейство функций spawn(). Они принимают вкачестве аргумента имя программы, создают новый экземпляр ее процесса изапускают его.
В Linux нет такой функции, которая дала бы все это за одни заход. Вместо этогоимеются функция fork(), создающая дочерний процесс, который является точнойкопией родительского процесса, и семейство функций exec(), заставляющихтребуемый процесс перестать быть экземпляром одной программы и превратитьсяв экземпляр другой программы.
Чтобы создать новый процесс, нужно сначала с помощью функции fork() создатькопию текущего процесса, а затем с помощью функции exec() преобразовать однуиз копий в экземпляр запускаемой программы.
Вызов функции fork()
Вызывая функцию fork(), программа создает свой дубликат, называемыйдочерним процессом. Родительский процесс продолжает выполнять программу стой точки, где была вызвана функция fork(). То же самое делает и дочернийпроцесс.
Как же различить между собой оба процесса? Во-первых, дочерний процесс – этоновый, только что появившийся в системе процесс, поэтому его идентификаторотличается от идентификатора родительского процесса. Таким образом, программа может вызывать функцию getpid() и узнать где именно она находится.Но сама функция fork() реализует другой способ: она возвращает разныезначения в родительском и дочернем процессах. Родительский процесс получаетидентификатор своего потомка, а дочернему процессу возвращается 0. В системенет процессов с нулевым идентификатором, так что программа легко разбираетсяв ситуации. Рассмотрим данную ситуацию на примере, учтите что первая частьинструкции if выполняется только в родительском процессе, тогда как ветвь else –только в дочернем. Пример[3]:
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
pid_t child_pid;
printf("ID процесса основной программы: %d\n", (int) getpid() );
child_pid = fork();
if (child_pid)
{
printf("Это родительский процесс, с ID %d\n", (int) getpid() );
printf("Дочерний процесс, с ID %d\n", (int) child_pid );
}
else
printf("Дочерний процесс с ID %d\n", (int) getpid() );
return 0;
}
Семейство функций exec()
Функции семейства exec() заменяют программу, выполняющуюся в текущемпроцессе, другой программой. Когда программа вызывает функцию exec(), еевыполнение немедленно прекращается и начинает работу новая программа.
Функции, в название которых присутствует суффикс 'p' (execvp() и execlp()),принимают в качестве аргумента имя программы и ищут эту программу вкаталогах, определяемых переменной среды PATH. Всем остальным функциянужно передавать полное путевое имя программы.
Функции, в названии которых присутствует суффикс 'v' (execv(), execvp(),execve()), принимают список аргументов программы в виде массива стоковыхуказателей, оканчивающегося NULL-указателем. Функции с суффиксом 'l'(excevl(), execlp(), execlve()), принимают список аргументов переменногоразмера.
Функции, в названии которых присутствует суффикс 'e' (execve(), execle()), вкачестве дополнительного аргумента принимают массив переменных среды. Этотмассив содержит строковые указатели и оканчивается пустым указателем. Каждаястрока должна иметь вид ''Переменная = значение''.
Поскольку функция exec() заменяет одну программу другой, она никогда невозвращает значение – только если вызов программы оказался невозможен вслучае ошибки.Список аргументов, передаваемых программе, аналогичен аргументам команднойстоки, указываемым при запуске программы в интерактивном режиме. Их тожеможно получить с помощью параметров argc и argv функции main(). Незабывайте: когда программу запускает интерпретатор команд, первый элементмассива argv будет содержать имя программы, а далее будут находитьсяпереданные программе аргументы. Аналогичным образом следует поступить,формируя список аргументов для функции exec().
Совместное использование функций fork() и exec()
Стандартная методика запуска одной программы из другой такова: сначала спомощью функции fork() создается дочерний процесс, затем в нем вызываетсяфункция exec().
Это позволяет главной программе продолжать выполнение в родительскомпроцессе. В качестве примера напишем программу которая отображает корневойкаталог. Пример [4]:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
int spawn(char* program, char** arg_list)
{
pid_t child_pid;
child_pid = fork();
if(child_pid)
return child_pid;
else {
execvp (program, arg_list);
fprintf (stderr, "an error occured in execvp\n");
abort();
}
}
int main()
{
int child_status;
char* arg_list[] = {"ls","-l","/",NULL};
spawn ("ls", arg_list);
wait (&child_status);
printf("done\n");
return 0;
}Системные вызовы wait()
Самая простая функция в семействе называется wait(). Она блокируетвызывающий процесс до тех пор, пока один из его дочерних процессов незавершиться (или не произойдет ошибка).
Пример использования данной функции приведен выше.
Функция waitpid() позволяет дождаться завершения конкретного дочернегопроцесса.
Функция wait3() возвращает информацию о статистике использованияцентрального процессора завершившемся дочерним процессом.Функция wait4() позволяет задать дополнительную информацию о том, какихпроцессов следует дождаться.
Порядок выполнения работы.
1. Прочитать методический материал.
2. Набрать код и произвести компиляцию примеров программ.
3. Проверить работоспособность программ.
4. Разобраться с функциями и системными вызовами.
Скачать Операционные системы. Лабораторная работа  lab2_1.zip [177,56 Kb] (cкачиваний: 77)

Информация

Комментировать статьи на нашем сайте возможно только в течении 60 дней со дня публикации.

Популярные новости

Статистика сайта



Rambler's Top100



 
Copyright © НеОфициальный сайт факультета ЭиП