You are on page 1of 13

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

Государственное образовательное учреждение высшего профессионального


образования

«ТОМСКИЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

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

Кафедра ВТ

Отчет по лабораторной работе №4


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

Знакомство с объектом процесс, основными механизмами


передачи данных между процессами и синхронизацией
взаимодействующих процессов в ОС Unix

Выполнил:
студент гр. 8В53
Сидоров А. О.

Проверил:
доцент каф. ВТ
Шерстнев В.С.

Томск 2008
Цель работы
Ознакомиться с объектом процесс, основными механизмами передачи данных между процессами, а
также синхронизацией взаимодействующих процессов в ОС Unix
Ход работы
1. Ознакомился с теоретическим материалом
2. Изучил работу команд для работы с процессами:
1. ps (process status) отображает статусы процессов, запущенных в системе.
2. jobs отображает список активных заданий
3. fg (foreground) служит для возобновления выполнения задания на переднем плане
4. bg (background) служит для запуска в фоновом режиме приостановленного процесса
5. kill позволяет уничтожить процесс
6. killall завершает процессы по имени
3. Создал 3 приложения «клиент-сервер»
3.1. Создал приложение «клиент-сервер», в котором родительский процесс (сервер) порождает
дочерний процесс (клиент). Родительский поток размещает данные (символы) в разделяемой
памяти, а дочерний считывает ее и анализирует (определяет, какие буквы хранятся в разделяемой
памяти). При этом синхронизация потоков обеспечивается при помощи семафоров.
Исходный код:
#include <stdio.h>
#include <cerrno>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

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


#define SKEY 1234L

union semun
{
int val;
struct semid_ds *buf;
ushort *array;
};

int main()
{
time_t seconds;
time(&seconds);
srand((unsigned)seconds);

int asciiStart = 65;


int asciiFinish = 90;
int asciiShift = asciiFinish - asciiStart + 1;

//Semaphore initialization
int flag = SVSEM_MODE | IPC_CREAT;

int semid = semget(SKEY, 1, flag);

union semun arg;


struct semid_ds seminfo;
arg.buf = &seminfo;
arg.val = 1;
semctl(semid, 0, SETVAL, arg);
//!

//SharedMemory initialization
int length = 20;
int sharedMemoryId = shmget(ftok("sharedMemory", 0), length, flag);

char *sharedMemoryPointer;
struct shmid_ds sharedMemoryBuf;
//!

//Semaphore locking
struct sembuf sembuf;
sembuf.sem_num = 0;
sembuf.sem_flg = 0;
sembuf.sem_op = -1;
semop(semid, &sembuf, 1);
//!

pid_t pid;
if ((pid = fork()) == 0)
{
//Semaphore locking
int childFlag = SVSEM_MODE | IPC_EXCL;
int childSemid = semget(SKEY, 1, childFlag);
struct sembuf childSembuf;
childSembuf.sem_num = 0;
childSembuf.sem_flg = 0;
childSembuf.sem_op = -1;
semop(semid, &childSembuf, 1);
//!

sharedMemoryPointer = (char*)shmat(sharedMemoryId, NULL, 0);


shmctl(sharedMemoryId, IPC_STAT, &sharedMemoryBuf);
char letters[asciiShift];
for (int i = 0; i < asciiShift; i++)
letters[i] = 0;
for (int i = 0; i < length; i++)
((int)letters[(int)*sharedMemoryPointer++ - asciiStart])++;
printf("Child: Shared memory contents:\n");
int k = 0;
for (int i = 0; i < asciiShift; i++)
{
if (((int)letters[i]) != 0)
{
printf("%c - %i\t", (char)(i + asciiStart), (int)letters[i]);
k++;
}
if (k == 5)
{
printf("\n");
k = 0;
}
}

if (k != 0)
printf("\n");

//Semaphore unlocking
childSembuf.sem_num = childSembuf.sem_flg = 0;
childSembuf.sem_op = 1;
semop(childSemid, &childSembuf, 1);
//!

printf("Child: Exit\n\n");

exit(0);
}

printf("Parent: Start filling shared memory\n");


printf("Parent: Shared memory contents following characters: \n");
sharedMemoryPointer = (char*)shmat(sharedMemoryId, NULL, 0);
shmctl(sharedMemoryId, IPC_STAT, &sharedMemoryBuf);
for (int i = 0; i < sharedMemoryBuf.shm_segsz; i++)
{
int number = rand() % asciiShift + asciiStart;
*sharedMemoryPointer++ = (char)number;
printf("%c ", (char)number);
}
printf("\n");
printf("Parent: Finish filling shared memory\n\n");

//Semaphore unlocking
sembuf.sem_num = sembuf.sem_flg = 0;
sembuf.sem_op = 1;
semop(semid, &sembuf, 1);
//!

waitpid(pid, NULL, 0);


semctl(semid, 0, IPC_RMID);
shmctl(sharedMemoryId, IPC_RMID, NULL);

printf("Parent: Exit");

exit(0);
}
Скомплировал и запустил программу:

Скриншот демонстрирует алгоритм работы программы:


1. Процесс1 блокирует семафор
2. Процесс1 заполняет общую память
3. Процесс1 разблокирует семафор и ждет завершения процесса2
4. Процесс2 считывает данные из общей памяти и затем анализирует их
5. Процесс2 завершает работу
6. Процесс1 завершает работу
3.2. Создал 2 приложения, взаимодействующих посредством именованных каналов. Приложение1
запрашивает отсутствующий у него функционал (метод Multiplicate) у приложения2.
Исходный код:
ira21.cpp:
#include <unistd.h>
#include <stdio.h>
#include <cerrno>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <string>

#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH


#define FIFO1 "fifo1"
#define FIFO2 "fifo2"
#define MAXLINE 10

int main()
{
time_t seconds;
time(&seconds);
srand((unsigned)seconds);

int readFd = -1, writeFd = -1;

unlink(FIFO1);
unlink(FIFO2);

mkfifo(FIFO1, FILE_MODE);
mkfifo(FIFO2, FILE_MODE);

writeFd = open(FIFO2, O_WRONLY);


if (writeFd == -1)
return 1;
readFd = open(FIFO1, O_RDONLY);
if (readFd == -1)
return 1;

char input1[MAXLINE];
int inp1 = rand() % 10 + 1;
sprintf(input1, "%i", inp1);
char input2[MAXLINE];
int inp2 = rand() % 10 + 1;
sprintf(input2, "%i", inp2);

write(writeFd, input1, MAXLINE);


write(writeFd, input2, MAXLINE);

char resultString[MAXLINE];
ssize_t n;
while ((n = read(readFd, resultString, MAXLINE)) > 0)
{
resultString[n] = 0;
break;
}

printf("Process1: Thank you, Process2! The result is ");


printf(resultString);
close(readFd);
close(writeFd);
unlink(FIFO1);
unlink(FIFO2);
exit(0);
}
ira22.cpp:
#include <unistd.h>
#include <stdio.h>
#include <cerrno>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <string>

#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH


#define FIFO1 "fifo1"
#define FIFO2 "fifo2"
#define MAXLINE 10

int Multiplicate(int x, int y);

int main()
{
int readFd = -1, writeFd = -1;

readFd = open(FIFO2, O_RDONLY, 0);


if (readFd == -1)
return 1;
writeFd = open(FIFO1, O_WRONLY, 0);
if (writeFd == -1)
return 1;

char input1[MAXLINE];
char input2[MAXLINE];

ssize_t n;
while ((n = read(readFd, input1, MAXLINE)) > 0)
{
input1[n] = 0;
break;
}
int inp1 = atoi(input1);
printf("Process2: Received inp1 = %i\n", inp1);
while ((n = read(readFd, input2, MAXLINE)) > 0)
{
input2[n] = 0;
break;
}
int inp2 = atoi(input2);
printf("Process2: Received inp2 = %i\n", inp2);

printf("Process2: Starting calculations\n");


int result = Multiplicate(inp1, inp2);
char resultString[MAXLINE];
sprintf(resultString, "%i", result);
printf("Process2: Finished calculations\n");

printf("Process2: Sending the result...\n");

write(writeFd, resultString, MAXLINE);

close(readFd);
close(writeFd);
}

int Multiplicate(int x, int y)


{
return x * y;
}
Скомпилировал и запустил созданные приложения:

Процесс ira21.exe запускается в фоновом режиме. После запуска ira22.exe получает два исходящих
параметра от процесса ira21.exe. Совершив необходимые вычисления, процесс ira22.exe отправляет
ответ ira21.exe, за что тот его весьма вежливо благодарит.
3.3. Создал 3 приложения, взаимодействующих при помощи очередей сообщений. Приложение1
реагирует текст, вводимый в консоль, и вызывает сообщения, которые обрабатываются
приложением2 и приложением3.
Исходный код:
ira41.cpp:
#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 <string>

struct
{
long mtype; /* тип сообщения */
char Data[256]; /* сообщение */
} Message;

int main()
{
key_t key;
int msgid;
char str[256];
key=ftok("message",0);
msgid=msgget(key, 0666 | IPC_CREAT);
while (true)
{
gets(str);
strcpy(Message.Data, str);
switch(str[0])
{
case '2': Message.mtype=1;
msgsnd(msgid, (struct msgbuf*)
(&Message), strlen(str)+1, 0);
break;
case '3': Message.mtype=2;
msgsnd(msgid, (struct msgbuf*)
(&Message), strlen(str)+1, 0);
break;
case 'q': Message.mtype=1;
msgsnd(msgid, (struct msgbuf*)
(&Message), strlen(str)+1, 0);
Message.mtype=2;
msgsnd(msgid, (struct msgbuf*)
(&Message), strlen(str)+1, 0);
sleep(10);
msgctl(msgid, IPC_RMID,
NULL);
exit(0);
default: break;
}
}
}
ira42.cpp:
#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>

struct
{
long mtype;
char Data[256];
} Message;

int main()
{
key_t key;
int msgid;
key=ftok("message",0);
msgid=msgget(key, 0666 | IPC_CREAT);
while (true)
{
msgrcv(msgid, (struct msgbuf*)(&Message), 256, 1, 0);
if (Message.Data[0]=='q')
break;
printf("Process2: %s \n", Message.Data);
}
//exit(0);
}
ira43.cpp:
#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>

struct
{
long mtype;
char Data[256];
} Message;

int main()
{
key_t key;
int msgid;
key=ftok("message", 0);
msgid=msgget(key, 0666 | IPC_CREAT);
while (true)
{
msgrcv(msgid, (struct msgbuf*)(&Message), 256, 2, 0);
if (Message.Data[0]=='q')
break;
printf("Process3: %s \n", Message.Data);
}
//exit(0);
}
Скомпилировал и запустил приложения:
Скриншот демонстрирует, что при нажатии «2» событие перехватывает приложение2, при нажатии «3»
- приложение3, а нажатие q завершает работу приложений.
Выводы
В ходе выполнения лабораторной работы был изучен объект процесс, основные механизмы передачи
данных между процессами (очереди сообщений, сегменты разделяемой памяти и каналы), а также
синхронизация взаимодействующих процессов в ОС Unix.посредством семафоров.