Московский Государственный Институт Электроники и Математики (Технический Университет)
Курсовая работа по дисциплине
«Операционные системы»
Вариант №6
Выполнили:
СК-41, АВТ
Проверил:
Преподаватель каф. МОСОиУ
Москва 2007
Лабораторная работа №1
Задание:
Написать программу выдачи списка всех пользователей, работающих в настоящее время в системе (имена связанных с ними терминалов и время входа в систему не указывать). Передать полученную информацию через межпроцессный канал в параллельный процесс, где вывести на экран. Предусмотреть возможность неоднократного внешнего прерывания. При каждом прерывании вывести время его поступления.
Описание:
I. Основная функция main()
1. Объявляем функцию обработки прерывании sig().
2. Объявляем дескрипторы межпроцессного канала g[2].
Это массив из двух элементов, первый элемент которого g[0] - дескрипторы межпроцессного канала на чтение из канала, второй - g[1] - дескрипторы межпроцессного канала на запись в канал.
3. Объявляем массив из 400 элементов buf[400], в который в дальнейшем будем считывать информацию из межпроцессного канала.
4. Системный вызов signal(SIGINT, sig) означает, что в случае прихода сигнала прерываний SIGINT , управление передается функции sig()
5. pipe(g) – Создание межпроцессного канала - коммуникационный канал между двумя взаимосвязанными процессами.
6. Для распараллеливания процессов используем системный вызов fork().
Программа разделяется на две идентичные копии, которые продолжают выполняться как два независимых процесса.
fork()==0 – процесс –сын.
fork()==1 – процесс – отец.
7. Процесс - сын:
7.1. При создании программы автоматически создаются три файла – пользовательские дескрипторы файлов:
0 /dev/tty - файл на стандартный ввод.
1 /dev/tty - файл на стандартный вывод.
2 /dev/tty - файл на стандартное выполнение.
Строка: close(1) означает закрытие стандартного вывода.
7.2. close(g[0]) - закрытие межпроцессного канала на чтение.
7.3. Системный вызов dup2 позволяет осуществить доступ к одному и тому же файлу из одного и того же пользовательского процесса через два различных пользовательских дескриптора файла.
dup2(g[1],1) - дублирование дескриптора межпроцессного канала на стандартный вывод.
После этого все данные будут выводиться не на экран (по умолчанию), а в межпроцессный канал.
7.4. close(g[1]) – удаляем копию.
7.5. Системный вызов execl осуществляет вызов новой команды вместо уже выполняющейся без возврата в вызывающую программу.
execl("/usr/bin/users","users",0) - вывод всех пользователей, работающих в данный момент в системе.
8. Процесс – отец:
8.1 close(g[1]) - закрытие межпроцессного канала на запись.
8.2 dup2(g[0],0) - дублирование дескриптора межпроцессного канала на стандартный ввод.
8.3 Следующим действием, в бесконечном цикле, считываем построчно из межпроцессного канала информацию в массив buf и выводим на экран его значение.
II. Функция обработки прерываний sig().
1. При каждом заходе в функцию увеличиваем счетчик прерываний на 1.
2. Если число прерываний достигло трех, выводим на экран сообщение:
Последние прерывание
время его поступления и выходим из программы
3. Если число прерываний меньше трех, выводим на экран сообщение:
Прерывание № n
И время его поступления - printf(__TIME__ "\n")
Код:
/* Включаем заголовочные файлы*/
#include <stdio. h>
#include <signal. h>
int i=0; /* Счетчик прерываний */
void sig() /* Функция обработки прерываний */
{
i++;
if(i==3)
{
printf("Последние прерывание\n");
printf(__TIME__ "\n");
exit(0);
}
else
{
printf("Прерывание № %d\n",i);
printf(__TIME__ "\n");
sleep(2);
}
}
main()
{
void sig(); /* Объявляем функцию обработки прерывании*/
int g[2]; /*Объявляем дескрипторы межпроцессного канала */
char buf[400]; /*Объявляем массив из 400 элементов*/
signal(SIGINT, sig); /* В случае прихода сигнала прерываний SIGINT
управление передается функции sig */
pipe(g); /* Создание межпроцессного канала*/
if (fork()==0) /* Распараллеливание процесса */
{ /* Процесс сын */
close(1); /* Закрытие стандартного вывода */
close(g[0]); /* Закрытие межпроцессного канала на чтение */
dup2(g[1],1); /* дублирование дескриптора межпроцессного канала на
стандартный вывод */
close(g[1]); /* Удаляем копию*/
execl("/usr/bin/users","users",0); /* Вывод всех пользователей, работающих в
данный момент в системе */
}
else
{ /* Процесс отец */
close(g[1]); /* Закрытие межпроцессного канала на запись */
dup2(g[0],0); /* дублирование дескриптора межпроцессного канала на
стандартный ввод */
while(1)
{
if(scanf("%s",buf)==EOF) /* Считывание построчно из межпроцессного
канала информацию в массив buf */
break;
printf("%s\n",buf); /* Вывод на экран значение переменной buf*/
}
sleep(2);
}
}
Лабораторная работа №2
Задание:
Выполнить лабораторную работу №1 на интерпретаторе команд shell.
Описание:
1. Объявляем переменную numsig=0; - счетчик прерываний.
2. Функция обработки прерываний signal()
numsig=`expr $numsig + 1`; - увеличиваем значение счетчика на 1.
expr –команда, осуществляющая вычисление арифметических выражений, выполняет следующие действия: + , - , * , / , % (остаток от деления).
expr $numsig + 1 –означает, что берем значение переменной numsig ($) и увеличиваем на 1.
`…` - присвоить результат выполнения команды.
Т. е. получается: присвоить переменной numsig результат выполнения команды: увеличить значение переменной numsig на 1.
Команда test осуществляет проверку файлов, числовых величин и цепочек символов.
Выражение: if test $numsig - eq 3 then
Означает: если значение переменной numsig равно трем (-eq 3), то ….
- eq ( = ) - le ( <= ) - qt ( > )
- lt (< ) - ge ( >= ) - ne ( != )
3. Основная функция
Команда trap означает, что при получении сигнала запускается программа обработчик сигналов.
trap signal SIGINT - в случае прихода сигнала прерывании (2 –SIGINT) управление передается функции signal().
Интерпретатор shell допускает объединение нескольких команд в конвейер (образуется с помощью операции "|") для их совместного выполнения. В этом случае информационная связь осуществляется через межпроцессный канал, и результат выполнения одной команды сразу поступает на вход другой.
who | awk '{print$1}'
Команда who выдает список всех пользователей, работающих в настоящее время в системе. Результат выполнения этой команды поступает на вход команды awk '{print$1}'.
Команда awk '{print$1}' – выводит на экран только первый столбец из полученной информации.
Код:
numsig=0; #счетчик прерывании
signal() #Функция обработки прерывании
{
numsig=`expr $numsig + 1`;
echo "Последнее Прерывание";
date | awk '{print$4}';
sleep 2;
}
trap signal 2 #В случае прихода сигнала прерывании, управление передается в signal()
sleep 1;
who | awk '{print$1}'
sleep 1;
sleep 1;
sleep 1;


