ЦЕЛЬ РАБОТЫ:

реклама
ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ
Государственное образовательное учреждение высшего профессионального
образования
«ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»
Факультет автоматики и вычислительной техники
Кафедра ВТ
Отчет по лабораторной работе №4
по дисциплине «Операционные системы»
Процессы и межпроцессное взаимодействие
Выполнил:
студент гр. 8В53
Чернявский Е.И.
Проверил:
доцент каф. ВТ
Шерстнев В.С.
Томск 2008
Цель работы:
Практическое знакомство с объектом процесс, основными механизмами передачи данных между
процессами, а также синхронизацией взаимодействующих процессов в ОС Unix.
Задание:
Изучить базовые возможностей оболочки bash ОС Unix по управлению процессами (заданиями).
Разработать приложения реализующие схему «клиент» - «сервер» с использованием средств
межпроцессного взаимодействия: семафоров, разделяемой памяти, программных каналов и одной очереди
сообщений:
1. Ознакомиться с теоретическим материалом.
2. Запустить несколько заданий (например, команд просмотра файлов less), возвращаясь в командную
строку комбинацией клавиш Ctrl-Z и изучить действие команд ps, jobs, fg, bg, kill, killall.
3. Обеспечить синхронизацию процессов и передачу данных между ними на примере трех
приложений «клиент» - «сервер», создав два процесса (два исполняемых файла) – процесс
«клиент» (первый исполняемый файл) и процесс «сервер» (второй исполняемый файл), либо один
процесс (один исполняемый файл) порождающий дочерний процесс: процесс родитель «сервер» и
дочерний процесс «клиент»;
4. Обеспечить с помощью механизмов межпроцессного взаимодействия передачу информации от
«клиента» к «серверу» и, наоборот, в качестве типа передаваемой информации можно
использовать: данные, вводимые с клавиатуры; данные, считываемые из файла; данные,
генерируемые случайным образом и т. п.;
5. Если требуется, обеспечить синхронизацию процессов с использованием семафоров.
6. Обмен данными между процессами «клиент» - «сервер» для трех приложений осуществить с
использованием различных средств межпроцессного взаимодействия:
 разделяемая память (синхронизация процессов обязательна);
 программные каналы (именованные либо неименованные);
 очередь сообщений.
Порядок работы:
Задание 1. Ознакомиться с теоретическим материалом.
Для повышения эффективности функционирования ВС обеспечивают два вида взаимодействия процессов:
псевдопараллельное (исполнение на одной ВС) и параллельное (исполнение на разных ВС).
Существуют различные причины кооперации процессов:
 повышение скорости работы (один процесс в ожидании, другой выполняет полезную работу,
направленную на решение общей задачи);
 совместное использование данных (использование различными процессами одной и той же
динамической базы данных или разделяемого файла);
 модульная конструкция какой-либо системы (например, микроядерный способ построения ОС,
когда взаимодействие процессов осуществляется путем передачи сообщений через микроядро);
 для удобства работы пользователя (например, при одновременном редактировании и отладке
программы, процессы редактора и отладчика должны взаимодействовать).
Различают два вида процессов: кооперативные (влияют на взаимное поведение путем обмена
информацией) и независимые (деятельность процессов остается неизменной при любой принятой
информации).
По объему передаваемой информации и степени возможного воздействия на поведение другого процесса
все средства такого обмена можно разделить на три категории: сигнальные, канальные и разделяемая
память.
В случае сигнального обмена передается минимальное количество информации, достаточное для
извещения процесса о наступлении события. При канальном обмене информацией «общение» процессов
происходит через линии связи, предоставленные ОС. Объем передаваемой информации в этом случае в
единицу времени ограничен пропускной способностью линий связи.
При использовании процессами разделяемой памяти совместно используется некоторая область адресного
пространства, формируемая ОС. Этот способ обмена информацией представляет собой наиболее быстрый
способ взаимодействия процессов в одной вычислительной системе, но требует при использовании
повышенной осторожности.
Различают два способа адресации при обмене информацией между процессами:

прямую (процессы осуществляют операции обмена данными явно указывая имя или номер этих
процессов);
 непрямую (данные помещаются передающим процессом в некоторый промежуточный объект для
хранения данных с адресом, откуда они затем могут быть изъяты каким-либо другим процессом).
Прямая адресация может быть двух типов:
 симметричной: процессы (принимающие и передающие данные) указывают имена своих
партнеров по взаимодействию, при этом ни один другой процесс не может вмешаться в процедуру
симметричного прямого общения двух процессов, перехватить посланные или подменить
ожидаемые данные;
 асимметричной: только один из взаимодействующих процессов указывает имя своего партнера по
кооперации, а второй процесс в качестве возможного партнера рассматривает любой процесс в
системе.
Следует выделить две различные модели передачи данных по каналам связи:
поток ввода-вывода (не важна структура данных, не осуществляется их интерпретация; процесс,
прочитавший 100 байт из линии связи, не знает, были ли они переданы одновременно, пришли от одного
процесса или от разных. Примером такой модели является «pipe» (канал);
сообщения (на передаваемые данные налагается некоторая структура, весь поток информации разделяется
на отдельные сообщения, вводя между данными, по крайней мере, границы сообщений).
Наиболее простой вариант пайпа (канала), а именно неименованный канал, создает оболочка Unix между
программами, запускаемыми из командной строки, разделенными символом «|».
Команды для работы с процессами.
Команда ps выдает список протекающих в настоящее время процессов, с параметром –aux выводит
полный список процессов.
Команда jobs выдает список процессов, запущенных пользователем.
Команды fg и bg служат для возобновления приостановленного процесса соответственно на «переднем
плане» или в фоновом режиме.
Команда kill служит для уничтожения процессов, а killall – для завершения процессов по имени.
Механизмы межпроцессного взаимодействия в ОС Unix.
При решении задачи синхронизации процессов и их взаимодействия посредством различных механизмов,
предоставляемых ОС, может потребоваться использование следующих системных вызовов:
 создание, завершение процесса, получение информации о процессе: fork(), exit(), getpid(), getppid(),
…;
 синхронизация процессов: signal(), kill(), sleep(), alarm(), wait(), pause(), semop(), semctl(),
semcreate(), …;
 создание информационного канала, разделяемой памяти, очереди сообщений и работа с ними:
pipe(), mkfifo(), read(), write(), msgget(), shmget(), msgctl(), shmctl(), …
Механизм межпроцессного взаимодействия (Inter-Process Communication Facilities - IPC) включает:
 средства, обеспечивающие возможность синхронизации процессов при доступе к совместно
используемым ресурсам – семафоры (semaphores);
 средства, обеспечивающие возможность посылки процессом сообщений другому произвольному
процессу – очереди сообщений (message queries);
 средства, обеспечивающие возможность наличия общей для процессов памяти – сегменты
разделяемой памяти (shared memory segments);
 средства, обеспечивающие возможность «общения» процессов, как родственных, так и нет, через
пайпы или каналы (pipes).
Наиболее общим понятием IPC является ключ, хранимый в общесистемной таблице и обозначающий
объект межпроцессного взаимодействия, доступный нескольким процессам. Обозначаемый ключом
объект может быть очередью сообщений, набором семафоров или сегментом
разделяемой памяти. Ключ имеет тип keyt, состав которого зависит от реализации и определяется в файле
<sys/types.h>. Ключ используется для создания объекта межпроцессного взаимодействия или получения
доступа к существующему объекту.
Задание 2. Запустить несколько заданий (например, команд просмотра файлов less), возвращаясь в
командную строку комбинацией клавиш Ctrl-Z и изучить действие команд ps, jobs, fg, bg, kill, killall.
Рассмотрим работу команд ps, kill и jobs, запустив на выполнение два процесса:
Запустим еще раз две задачи: команда yes будет посылать бесконечный набор символов y в /dev/null и в
некоторый файл y_file в домашнем каталоге. С помощью команд fg и bg можно переключаться между
процессами. Наконец, с помощью команды killall завершим выполнение всех процессов с именем yes. Как
видно из рисунка, в результате выполнения команды killall yes оба запущенных нами процесса
завершились:
Задание 3. Обеспечить синхронизацию процессов и передачу данных между ними на примере
приложения «клиент» - «сервер», создав два процесса (два исполняемых файла) – процесс «клиент»
(первый исполняемый файл) и процесс «сервер» (второй исполняемый файл). Обеспечить с помощью
механизмов межпроцессного взаимодействия передачу информации от «клиента» к «серверу» и,
наоборот, в качестве типа передаваемой информации можно использовать: данные, вводимые с
клавиатуры; данные, считываемые из файла; данные, генерируемые случайным образом и т. п. Если
требуется, обеспечить синхронизацию процессов с использованием семафоров. Обмен данными
между процессами «клиент» - «сервер» осуществить с использованием программных каналов
(именованных либо неименованных).
Два приложения – сервер и клиент – общаются между собой с помощью именованных каналов. По
каналам S2C_PIPE и C2S_PIPE сообщения «Ping?» и «Pong!» передаются от сервера клиенту, и от клиента
серверу соответственно:
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <cerrno>
#include <unistd.h>
#include <fcntl.h>
#include <malloc.h>
#include <strings.h>
#include <iostream.h>
#include <error.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#define MAXLINE 128
#define FILE_MODE ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )
#define PIPE_S2C "S2C_PIPE"
#define PIPE_C2S "C2S_PIPE"
const int PIPE_S2C_MODE = O_WRONLY; // write-only pipe
const int PIPE_C2S_MODE = O_RDONLY; // read-only pipe
int main() {
char str[ MAXLINE ]; // char array
ssize_t n; // buffer size
int readfd = -1; // error on default
int writefd = -1; // error on default
strcpy( str, "Ping?" ); // message for client
unlink( PIPE_S2C ); // delete PIPE_1 descriptor if exists
unlink( PIPE_C2S ); // delete PIPE_2 descriptor if exists
if( mkfifo( PIPE_S2C, FILE_MODE ) == EEXIST ) // check anyway if PIPE_1 exists
cout << "\n" << "[Server] -> * warning: pipe named " << PIPE_S2C " already exists!" << endl;
if( mkfifo( PIPE_C2S, FILE_MODE ) == EEXIST ) // check anyway if PIPE_1 exists
cout << "\n" << "[Server] -> * warning: pipe named " << PIPE_C2S " already exists!" << endl;
writefd = open( PIPE_S2C, PIPE_S2C_MODE ); // open write-only pipe
if( ( writefd != -1 ) ) {
// if pipe was succesfully opened
cout << "[Server] -> * write-only pipe opened..." << endl;
sleep( 1 );
write( writefd, str, strlen( str ) ); // sending message to client
cout << "[Server] -> [Client]: " << str << endl;
readfd = open( PIPE_C2S, PIPE_C2S_MODE ); // open read-only pipe
cout << "[Server] -> * waiting for response..." << endl;
sleep( 1 );
while( ( n = read( readfd, str, MAXLINE ) ) > 0 ) {
str[ n ] = 0;
cout << "[Server] -> * client responds: " << str << endl;
break;
}
close( readfd ); // close RO-pipe descriptor
close( writefd ); // close WO-pipe descriptor
unlink( PIPE_S2C ); // delete PIPE_1 descriptor if exists
unlink( PIPE_C2S ); // delete PIPE_2 descriptor if exists
}
else {
cout << "Unable to open pipes...";
return 1;
}
}
client.c:
#include <unistd.h>
#include <stdio.h>
#include <error.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream.h>
#include <strings.h>
#include <fstream.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define MAXLINE 128
#define FILE_MODE ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )
#define PIPE_S2C "S2C_PIPE"
#define PIPE_C2S "C2S_PIPE"
const int PIPE_S2C_MODE = O_RDONLY; // read-only pipe
const int PIPE_C2S_MODE = O_WRONLY; // write-only pipe
int main() {
char str[ MAXLINE ]; // char array
ssize_t n; // buffer size
int readfd = -1; // error on default
int writefd = -1; // error on default
while ( true ) {
readfd = open( PIPE_S2C, PIPE_S2C_MODE ); // open read-only pipe
if ( readfd != -1 ) {
cout << "[Client] -> * read-only pipe opened..." << endl;
sleep( 1 );
while( ( n = read( readfd, str, MAXLINE ) ) > 0) {
str[ n ] = 0;
cout << "[Client] -> * server says: " << str << endl;
break;
}
strcpy( str, "Pong!" ); // message for server
writefd = open( PIPE_C2S, PIPE_C2S_MODE ); // open write-only pipe
sleep( 1 );
cout << "[Client] -> * write-only pipe opened..." << endl;
sleep( 1 );
cout << "[Client] -> [Server]: " << str << endl;
write( writefd, str, strlen( str ) ); // sending message to client
close( readfd ); // close RO-pipe descriptor
close( writefd ); // close WO-pipe descriptor
break;
}
sleep( 1 );
}
return 1;
}
Запустим программу-сервер в фоновом режиме, затем клиента. Ниже, на рисунке можно видеть процесс
компиляции программ, их запуска и дальнейшей работы – общения через именованные каналы:
Вывод: В данной лабораторной работе были рассмотрены такое понятие как «процесс» и методы работы с
процессами, а также способ обмена данными между процессами, называемый «пайпами» (pipe).
Скачать