You are on page 1of 9

Федеральное агентство по образованию

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

Факультет автоматики и вычислительной техники


Кафедра ВТ

ЛАБОРАТОРНАЯ РАБОТА №4

по дисциплине
«Операционные системы»

Выполнил:
Студент группы 8В51 _________ М. С. Гриценко

Руководитель:
_________ А. В. Замятин

Томск – 2008
2
Цель: практическое знакомство с объектом процесс, основными механиз-
мами передачи данных между процессами, а также синхронизацией взаимодей-
ствующих процессов в ОС Unix.
Задание: изучить базовые возможности оболочки bash ОС Unix по управле-
нию процессами (заданиями). Разработать приложения реализующие схему «кли-
ент-сервер» с использованием средств межпроцессорного взаимодействия: сема-
форов, разделяемой памяти, программных каналов и одной очереди сообщений.

Ход работы
1. Ознакомились с теоретическим материалом
2. Программа-клиент создаёт случайную последовательность случайной дли-
ны, программа-сервер должна определить количество чисел и их сумму (чи-
сел не больше 100, все положительные и не превышают 100).
Листинг программы с общей памятью (синхронизация семафорами)
#include <unistd.h>
#include <stdio.h>
#include <error.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <time.h>
#include <iostream.h>

#define FLAGS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)


#define MYKEY 1234L
#define MKEY 1235L

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("Parent : Creating semaphore... \n");
int semid = semget( MYKEY, 1, FLAGS|IPC_CREAT);
3
arg.val = 2;
semctl( semid, 0, SETVAL, arg);

printf("Parent : initialization public memory \n");


// инициализация общей памяти
int mid = shmget( MKEY, 100, FLAGS|IPC_CREAT);
short *ptr = (short *)shmat( mid, NULL, 0);
printf("Parent : initialization OK \n");

if (( pid =fork()) ==0) //дочерний процесс


{
printf(" Child : Child process was created...\n");

int ch_semid = semget( MYKEY, 1, FLAGS|IPC_EXCL);


printf(" Child : opening semaphore... \n");

// инициализация общей памяти


printf(" Child : initalization public memory\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(" Child : printing in memory\n");
// запись в общую память

int count= 1+ rand()%90;


int i;
int sum = 0;
for ( i=0; i<100; i++) ch_ptr[i]=0;
for ( i=0; i<count; i++)
{
ch_ptr[i] =1+rand()%100;
sum += ch_ptr[i];
}
printf(" Child : the sum is %d \n", sum);

sleep(3);

semop( ch_semid, &ch_buf, 1); // запуск основной проги

//уход в режим ожидания


printf(" Child : wait answer from Parent\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(" Child : reseved answer from Parent ");


if ( *ch_ptr == count) printf("OK"); else printf("Failure");
printf("\n Child : i'm die \n");

exit(0); }
printf("Parent : wait for unlock simaphore ..\n");
pbuf.sem_num = pbuf.sem_flg = pbuf.sem_op = 0;
semop( semid, &pbuf, 1); //
printf("Parent : unlocked by child,waiting for unlock child \n");
4
// считывание с общей памяти
int j=0;
int psum =0;

while (ptr[j]>0) psum+=ptr[j++];


*ptr = j; //ответ для дочернего процесса
printf("Parent : the sum is %d \n", psum);

sleep(2);

printf("Parent : start unlocking child\n");


pbuf.sem_num = pbuf.sem_flg = 0;
pbuf.sem_op = -1;
semop( semid, &pbuf, 1);
printf("Parent : unlock child\n");

printf("Parent : wait for chaild terminated\n");


waitpid( pid, NULL, 0);
printf("Parent : child, died \n");

printf("Parent : remove semaphor \n");


semctl( semid, 0, IPC_RMID);
printf("Parent : remove public memory \n");
shmctl( mid, IPC_RMID, NULL);
return 0;
}
Вывод программы:
Parent : Creating semaphore...
Parent : initialization public memory
Parent : initialization OK
Child : Child process was created...
Child : opening semaphore...
Child : initalization public memory
Child : printing in memory
Child : the sum is 212
Parent : wait for unlock simaphore ..
Child : wait answer from Parent
Parent : unlocked by child,waiting for unlock child
Parent : the sum is 212
Parent : start unlocking child
Child : reseved answer from Parent OK
Child : i'm die
Parent : unlock child
Parent : wait for chaild terminated
Parent : child, died
Parent : remove semaphor
Parent : remove public memory
5
3. Программа-клиент записывает в файлы слова, которые посылает про-
грамма-сервер. По слову exit обе программы прекращают работать. Лис-
тинг на основе очереди FIFO.
Сервер
#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 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<<"Server start..."<<endl;
unlink(FIFO1);
unlink(FIFO2);

if (mkfifo(FIFO1, FILE_MODE) == EEXIST)cout<<"\n Pipes is exist"<<endl;


if (mkfifo(FIFO2, FILE_MODE) == EEXIST)cout<<"\n Pipes is exist"<<endl;
cout<<"You may type words..."<<endl;

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<<str2<<endl;
break;
}
if (strcmp(str, "exit")==0) break;
}
close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);
cout<<"Server is shut down"<<endl;
}else cout<<"can't open pipes.."<<endl;
return 0; }
Клиент
6
#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 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<<"Client was running..."<<endl;
while (1)
{
readfd = open(FIFO2, O_RDONLY, 0);
if (readfd!=-1)
{
while ((n=read(readfd, str, MAXLINE))>0)
{
str[n] = 0;
cout<<str<<endl;
break;
}

strcpy(str2, "ok from client");


writefd = open(FIFO1, O_WRONLY,0);
write(writefd, str2, strlen(str2));
close(readfd);
close(writefd);
}
sleep(1);
if (strcmp(str, "exit") ==0) break;
}
cout<<"Client is shut down";
cout.close();
return 0;
}
7
Результаты работы сервера
Server start...
You may type words...
one
ok from client
two
ok from client
three
ok from client
exit
ok from client
Server is shut down

Результат работы клиента


Client was running..
one
two
three
exit
Client is shut down

4. Программа-сервер записывает в очередь числа, программа-клиент считыва-


ет из очереди эти числа, считает их количество и сумму, удаляет очередь.
Сервер
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <error.h>
#include <iostream.h>

#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("Server :Make message queue\n");

int msgid = msgget( ftok("maxim",0), FLAGS|IPC_CREAT);


cout<< msgid<<endl;

struct msg s_msg;


s_msg.mtype =1;
printf("Server :Sending messages\n");
for (int i=1; i<100; i++)
{
8
s_msg.number = i;
msgsnd( msgid, &s_msg, sizeof(s_msg), IPC_NOWAIT);
}
printf("Server :Log out");

return 0;

}
Клиент
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <error.h>
#include <iostream.h>

#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("Client :Open message queue\n");

int msgid = msgget(ftok("maxim", 0), FLAGS);


cout<<msgid<<endl;
// if (msgid> 0)
{

struct msg c_msg;


c_msg.mtype =1;
printf("Client :Receiving messages\n");

int count=0, sum =0;

while (msgrcv( msgid, &c_msg,sizeof(c_msg), 0, IPC_NOWAIT)>0)


{
count++;
sum+=c_msg.number;
};

printf("Client :The count is %d\n", count);


printf("Client :The sum is %d\n", sum);
printf("Client :Removing queue \n");
msgctl( msgid, IPC_RMID, NULL);

}
printf("Server :Log out");
return 0;

Выводы:В ходе проделанной лабораторной работы мы познакомились с


основными механизмами передачи данных между процессами, а также их синхро-
9
низацией. Синхронизация процессов мало отличается от синхронизации по-
токов, поэтому это очень важное и кропотливое дело.