Лабораторная работа №4 по дисциплине «Операционные системы»
Федеральное агентство по образованию
Государственное образовательное
учреждение высшего профессионального образования
«ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

Факультет автоматики и вычислительной техники
Кафедра ВТ

ЛАБОРАТОРНАЯ РАБОТА №4
по дисциплине
«Операционные системы»
Выполнил:
Студент группы 8В51 _________ М. С. Гриценко
Руководитель:
_________ А. В. Замятин
Томск – 2008
Цель: практическое знакомство с объектом процесс, основными механизмами передачи данных между процессами, а также синхронизацией взаимодействующих процессов в ОС Unix.
Задание: изучить базовые возможности оболочки bash ОС Unix по управлению процессами (заданиями). Разработать приложения реализующие схему «клиент-сервер» с использованием средств межпроцессорного взаимодействия: семафоров, разделяемой памяти, программных каналов и одной очереди сообщений.
Ход работы
Ознакомились с теоретическим материалом
Программа-клиент создаёт случайную последовательность случайной длины, программа-сервер должна определить количество чисел и их сумму (чисел не больше 100, все положительные и не превышают 100).
Листинг программы с общей памятью (синхронизация семафорами)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FLAGS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
#define MYKEY 1234L
#define MKEY 1235L
using namespace std;
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
int main( int argc, char *argv[])
{
pid_t pid; // идентификатор дочернего процесса
union semun arg;
struct sembuf pbuf;
//srand((unsigned)time(NULL));
printf("Родитель : создание семафора\n");
int semid = semget( MYKEY, 1, FLAGS|IPC_CREAT);
arg.val = 2;
semctl( semid, 0, SETVAL, arg);
printf("Родитель : инициализация общей памяти \n");
// инициализация общей памяти
int mid = shmget( MKEY, 100, FLAGS|IPC_CREAT);
short *ptr = (short *)shmat( mid, NULL, 0);
printf("Родитель : инициализация успешно завершена \n");
if (( pid =fork()) ==0) //дочерний процесс
{
printf(" Потомок : процесс-поток создан\n");
int ch_semid = semget( MYKEY, 1, FLAGS|IPC_EXCL);
printf(" Потомок : открытие семафора... \n");
// инициализация общей памяти
printf(" Потомок : инициализация общей памяти\n");
int ch_mid = shmget( MKEY, 100, FLAGS|IPC_EXCL);
short *ch_ptr = (short *)shmat( ch_mid, NULL, 0);
struct sembuf ch_buf;
ch_buf.sem_num = ch_buf.sem_flg = 0;
ch_buf.sem_op = -1;
semop( ch_semid, &ch;_buf, 1);
printf(" Потомок : запись в общую память\n");
// запись в общую память
int count= 20;
int i;
int sum = 0;
for ( i=0; i<100; i++) ch_ptr[i]=0;
for ( i=0; i
ch_ptr[i] =20;
sum += ch_ptr[i];
}
printf(" Потомок : записано число %d \n", sum);
sleep(3);
semop( ch_semid, &ch;_buf, 1); // запуск основной проги
//уход в режим ожидания
printf(" Потомок : ожидание ответа от родителя\n");
union semun ch_arg;
ch_arg.val = 1;
semctl( ch_semid, 0, SETVAL, ch_arg);
ch_buf.sem_op = ch_buf.sem_flg = ch_buf.sem_num =0;
semop( ch_semid, &ch;_buf, 1);
printf(" Потомок : получен ответ от родителя ");
if ( *ch_ptr == count) printf("ОК"); else printf("Ошибка");
printf("\n Потомок : я уничтожен \n");
exit(0);
}
printf("Родитель : ожидание открытия семафора...\n");
pbuf.sem_num = pbuf.sem_flg = pbuf.sem_op = 0;
semop( semid, &pbuf;, 1); //
printf("Родитель : считывание с общей памяти \n");
// считывание с общей памяти
int j=0;
int psum =0;
while (ptr[j]>0) psum+=ptr[j++];
*ptr = j; //ответ для дочернего процесса
printf("Родитель : число равно %d \n", psum);
sleep(2);
printf("Родитель : начато открытие дочернего потока\n");
pbuf.sem_num = pbuf.sem_flg = 0;
pbuf.sem_op = -1;
semop( semid, &pbuf;, 1);
printf("Родитель : дочерний процесс разблокирован\n");
printf("Родитель : ожидание завершения потомка\n");
waitpid( pid, NULL, 0);
printf("Родитель : потомок уничтожен \n");
printf("Родитель : уничтожение семафора \n");
semctl( semid, 0, IPC_RMID);
printf("Родитель : освобождение общей памяти \n");
shmctl( mid, IPC_RMID, NULL);
return 0;
}
Вывод программы:
andrey@Andrey4623:~/laba4_1$ ./iEdit
Родитель : создание семафора
Родитель : инициализация общей памяти
Родитель : инициализация успешно завершена
Родитель : ожидание открытия семафора...
Потомок : процесс-поток создан
Потомок : открытие семафора...
Потомок : инициализация общей памяти
Потомок : запись в общую память
Потомок : записано число 400
Потомок : ожидание ответа от родителя
Родитель : считывание с общей памяти
Родитель : число равно 400
Родитель : начато открытие дочернего потока
Родитель : дочерний процесс разблокирован
Родитель : ожидание завершения потомка
Потомок : получен ответ от родителя ОК
Потомок : я уничтожен
Родитель : потомок уничтожен
Родитель : уничтожение семафора
Родитель : освобождение общей памяти
Программа-клиент записывает в файлы слова, которые посылает программа-сервер. По слову exit обе программы прекращают работать. Листинг на основе очереди FIFO.
Сервер
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXLINE 128
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
#define FIFO1 "fifo.1"
#define FIFO2 "fifo.2"
int main( int argc, char **argv)
{
int readfd =-1, writefd = -1;
size_t n = 0;
char str[MAXLINE];
char str2[MAXLINE];
cout<<"Сервер запущен"<
unlink(FIFO2);
if (mkfifo(FIFO1, FILE_MODE) == EEXIST)cout<<"\n Pipes is exist"<
writefd = open(FIFO2, O_WRONLY);
if ((writefd!=-1)){
while (1){
cin>>str;
write(writefd, str, strlen(str));
readfd = open(FIFO1, O_RDONLY);
while ((n = read(readfd, str2, MAXLINE))>0) {
str2[n] =0;
cout<
}
if (strcmp(str, "exit")==0) break;
}
close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);
cout<<"Сервер завершен"<
Клиент
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXLINE 128
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
#define FIFO1 "fifo.1"
#define FIFO2 "fifo.2"
int main( int argc, char **argv)
{
int readfd =-1, writefd = -1;
size_t n = 0;
char str[MAXLINE];
char str2[MAXLINE];
ofstream cout("log.txt");
cout<<"Клиент запущен"<
while (1)
{
readfd = open(FIFO2, O_RDONLY, 0);
if (readfd!=-1)
{
while ((n=read(readfd, str, MAXLINE))>0)
{
str[n] = 0;
cout<
break;
}
strcpy(str2, "Подтверждение от клиента");
writefd = open(FIFO1, O_WRONLY,0);
write(writefd, str2, strlen(str2));
close(readfd);
close(writefd);
}
sleep(1);
if (strcmp(str, "exit") ==0) break;
}
cout<<"Клиент завершен";
cout.close();
return 0;
}
Результаты работы сервера
andrey@Andrey4623:~/laba4_2$ ./server.exe
Сервер запущен
Набирайте слова
1
Подтверждение от клиента
2
Подтверждение от клиента
exit
Подтверждение от клиента
Сервер завершен
andrey@Andrey4623:~/laba4_2$
Результат работы клиента
Клиент запущен
1
2
exit
Клиент завершен
Программа-сервер записывает в очередь числа, программа-клиент считывает из очереди эти числа, считает их количество и сумму, удаляет очередь.
Сервер
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MYKEY 4321L
#define FLAGS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
struct msg
{
long mtype;
int number;
};
int main( int argc, char *argv[])
{
printf("Сервер: очередь создана\n");
int msgid = msgget( ftok("maxim",0), FLAGS|IPC_CREAT);
cout<< msgid<
struct msg s_msg;
s_msg.mtype =1;
printf("Сервер: отправляем данные\n");
int k=0;
for (int i=1; i<100; i++)
{
s_msg.number = i;
msgsnd( msgid, &s;_msg, sizeof(s_msg), IPC_NOWAIT);
k+=i;
}
//printf("Сервер: количество чисел 99\n");
//printf("Cthdth : сумма %d\n", k);
printf("Сервер: завершаем работу");
return 0;
}
Клиент
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MYKEY 4321L
#define FLAGS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
struct msg
{
long mtype;
int number;
};
int main( int argc, char *argv[])
{
printf("Клиент: очередь открыта\n");
int msgid = msgget(ftok("maxim", 0), FLAGS);
cout<
// if (msgid> 0)
{
struct msg c_msg;
c_msg.mtype =1;
printf("Клиент: чтение данных\n");
int count=0, sum =0;
while (msgrcv( msgid, &c;_msg,sizeof(c_msg), 0, IPC_NOWAIT)>0)
{
count++;
sum+=c_msg.number;
};
printf("Клиент : количество чисел %d\n", count);
printf("Клиент : сумма %d\n", sum);
printf("Клиент : очередь удалена \n");
msgctl( msgid, IPC_RMID, NULL);
}
printf("Клиент: завершаем работу");
return 0;
}
andrey@Andrey4623:~/laba4_3$ ./server.exe
Сервер: очередь создана
0
Сервер: отправляем данные
Сервер: завершаем работуandrey@Andrey4623:~/laba4_3$
andrey@Andrey4623:~/laba4_3$ ./client.exe
Клиент: очередь открыта
0
Клиент: чтение данных
Клиент : количество чисел 99
Клиент : сумма 198
Клиент : очередь удалена
Клиент: завершаем работуandrey@Andrey4623:~/laba4_3$
Выводы:В ходе проделанной лабораторной работы мы познакомились с основными механизмами передачи данных между процессами, а также их синхронизацией. Синхронизация процессов мало отличается от синхронизации потоков, поэтому это очень важное и кропотливое дело.
страница 1
скачать
Другие похожие работы: