Вы находитесь на странице: 1из 7

Лабораторная работа №4

«Организация межпроцессного взаимодействия


в операционной системе Linux»

Цель работы: изучение принципов межпроцессных коммуникаций, организация и


проведение сравнительного анализа каналов передачи данных между процессами и потоками в
операционной системе Linux.

Задание
Напишите программу, которая измеряет скорость передачи данных между процессами
используя два вида межпроцессных коммуникаций – неименованные каналы и сегменты общей
памяти. Передаваемые данные должны быть представлены в виде произвольного набора
символов.
Используйте свою программу для исследования скорости передачи пакетов данных
различных размеров – от нескольких байт до нескольких десятков мегабайт. Результаты
измерений представьте в виде графиков – зависимость времени передачи данных между
процессами от объема передаваемых данных для неименованных каналов и сегментов общей
памяти. Графики представьте в логарифмическом масштабе (по объему передаваемых данных).
В случае необходимости, для синхронизации процессов (потоков) используйте либо
семафоры (функции semget(), semctl() и semop() из <sys/sem.h>), либо мьютексы и условные
переменные.
В процессе отладки программ у Вас могут возникать ситуации, когда
программы будут аварийно заканчиваться или прерываться Вами прежде, чем они
уничтожат созданные ими общие сегменты памяти. Такие сегменты не удаляются в
системе автоматически и могут накапливаться в течение многих дней. Накопление
таких "забытых" общих сегментов может привести к тому, что будет исчерпан
системный лимит на количество общих сегментов, и очередной вызов shmget
закончится с ошибкой. Для того чтобы этого не происходило, регулярно выполняйте
очистку сегментов памяти и семафоров, созданных Вами (см. команды ipcs и ipcrm).

Ход работы

Листинг программы.
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/errno.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <chrono>
#include <ctime>
#include <math.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>

using namespace std;

int8_t *TestArray;
int64_t TestArray_SizeInBytes;
Лист
Лабораторная работа №4 ТОГУ, ИС-51, Храмцов А.А.
по Системному ПО 1
void PipeTransmission()
{
int PipeFileDescriptors[2];
if (pipe(PipeFileDescriptors) == -1)
{
cout << "Could Not Create Pipe" << endl;
exit(1);
}
int ReadDescriptor = PipeFileDescriptors[0];
int WriteDescriptor = PipeFileDescriptors[1];
int ChildProcessID = 0;
if ((ChildProcessID = fork()) < 0)
{
cout << "Could Not Fork A New Process" << endl;
sleep(3);
exit(2);
}
//Parent Process. (Has ChildProcessID Initialized).
if (ChildProcessID != 0)
{
//Closing Read Descriptor.
close(ReadDescriptor);
int64_t StartTime = chrono::system_clock::now().time_since_epoch().count();
//Getting int64_t Pointer To Array Beginning.
int64_t *StartTimePlaceInArray = (int64_t *)TestArray;
//Packing StartTime Into First 8 Array Elements.
*StartTimePlaceInArray = StartTime;
for (int i = 8; i < TestArray_SizeInBytes; i++)
{
TestArray[i] = 1;
}
//Sending TestArray To Child Process.
write(WriteDescriptor, TestArray, TestArray_SizeInBytes);
close(WriteDescriptor);
}
//Child Process. (Did Not Initialize ChildProcessID).
else
{
//Closing Write Descriptor.
close(WriteDescriptor);
//Waiting For Writer To Write Enough Symbols To Pipe.
while (read(ReadDescriptor, TestArray, TestArray_SizeInBytes) != 0) {};
int64_t *StartTimePlaceInArray = (int64_t *)TestArray;
int64_t StartTime = *StartTimePlaceInArray;
double DeltaTime = (chrono::system_clock::now().time_since_epoch().count() - StartTime) /
pow(10, 9);
cout << "Time Taken To Transfer " << TestArray_SizeInBytes << " Bytes Of Data Through Pipe: "
<< DeltaTime << " Seconds" << endl;
close(ReadDescriptor);
}
}

Лист
Лабораторная работа №4 ТОГУ, ИС-51, Храмцов А.А.
по Системному ПО 2
void SharedMemoryTransmission()
{
int ChildProcessID = 0;
if ((ChildProcessID = fork()) < 0)
{
cout << "Could Not Fork A New Process" << endl;
sleep(3);
exit(2);
}
//Parent Process. (Has ChildProcessID Initialized).
if (ChildProcessID != 0)
{
key_t SharedMemoryKey = ftok(".", 'x');
//0666 - 000 110 110 110 - Every Permission, Except For Execution, For Everyone.
//IPC_CREAT - Execution For WorkGroup?
int SharedMemorySegment_ID = shmget(SharedMemoryKey, TestArray_SizeInBytes,
IPC_CREAT | 0666);
if (SharedMemorySegment_ID < 0)
{
cout << "Server: Could Not Allocate Shared Memory Segment" << endl;
sleep(3);
exit(2);
}
int8_t* SharedMemoryStartAddress = (int8_t*)shmat(SharedMemorySegment_ID, NULL, 0);
if (SharedMemoryStartAddress == (int8_t*)-1)
{
cout << "Server: Could Not Attach A Shared Memory Segment To Process" << endl;
sleep(3);
exit(2);
}
int64_t StartTime = chrono::system_clock::now().time_since_epoch().count();
//Getting int64_t Pointer To Array Beginning.
int64_t *StartTimePlaceInSharedMemory = (int64_t *)(SharedMemoryStartAddress + 1);
//Packing StartTime Into 8 Shared Memory Bytes.
*StartTimePlaceInSharedMemory = StartTime;

//Do Not Overwrite 1-9 Memory Cells After SharedMemoryStartAddress (They Contain
StartTime).
int8_t* CurrentMemoryCell = (int8_t*)(SharedMemoryStartAddress + 9);
for (int64_t i = 10; i < TestArray_SizeInBytes; i++)
{
*CurrentMemoryCell = '1';
CurrentMemoryCell++;
}

//Signaling "Client" To Start It's Work.


*SharedMemoryStartAddress = 'S';

//Waiting For "Client" To Put "E" At The Beginning Of Shared Memory Segment. Checking It
Every Tick Is A Waste Of CPU Time.
while (*SharedMemoryStartAddress != 'E')
{
sleep(0.1);
Лист
Лабораторная работа №4 ТОГУ, ИС-51, Храмцов А.А.
по Системному ПО 3
}

//Detaching And Removing Shared Memory Segment.


shmdt(SharedMemoryStartAddress);
if (shmctl(SharedMemorySegment_ID, IPC_RMID, NULL) == -1)
{
cout << "Server: Could Not Remove A Shared Memory Segment" << endl;
sleep(3);
exit(2);
}
}
//Child Process. (Did Not Initialize ChildProcessID).
else
{
key_t SharedMemoryKey = ftok(".", 'x');
//0666 - 000 110 110 110 - Every Permission, Except For Execution, For Everyone.
//IPC_CREAT - Execution For WorkGroup?
int SharedMemorySegment_ID = shmget(SharedMemoryKey, TestArray_SizeInBytes,
IPC_CREAT | 0666);
if (SharedMemorySegment_ID < 0)
{
cout << "Client: Could Not Allocate Shared Memory Segment" << endl;
sleep(3);
exit(2);
}
int8_t* SharedMemoryStartAddress = (int8_t*)shmat(SharedMemorySegment_ID, NULL, 0);
if (SharedMemoryStartAddress == (int8_t*)-1)
{
cout << "Client: Could Not Attach A Shared Memory Segment To Process" << endl;
sleep(3);
exit(2);
}

//Waiting For "Server" To Inform Us That It Finished It's Task.


while (*SharedMemoryStartAddress != 'S')
{
sleep(0.1);
}
int TempVar;
for (int i = 0; i < TestArray_SizeInBytes; i++)
{
TempVar = *(SharedMemoryStartAddress + i);
}
//Recieving StartTime
int64_t *StartTimePlaceInSharedMemory = (int64_t *)(SharedMemoryStartAddress + 1);
int64_t StartTime = *StartTimePlaceInSharedMemory;
double DeltaTime = (chrono::system_clock::now().time_since_epoch().count() - StartTime) /
pow(10, 9);
cout << "Time Taken To Transfer " << TestArray_SizeInBytes << " Bytes Of Data Through Shared
Memory: " << DeltaTime << " Seconds" << endl;

//Putting "E" At The Beginning Of Shared Memory Segment (Signaling For Server To Delete
Shared Memory Segment).
Лист
Лабораторная работа №4 ТОГУ, ИС-51, Храмцов А.А.
по Системному ПО 4
*SharedMemoryStartAddress = 'E';
//Detaching Shared Memory Segment.
shmdt(SharedMemoryStartAddress);
}
}

int main(int argc, char *argv[])


{
bool UsePipes = atoi(argv[1]);
TestArray_SizeInBytes = atol(argv[2]);
//At Least 8 Bytes Needed For Pipes And At Least 9 - For Shared Memory.
if (TestArray_SizeInBytes < 9)
{
TestArray_SizeInBytes = 9;
}
TestArray = new int8_t[TestArray_SizeInBytes];
if (UsePipes)
{
PipeTransmission();
}
else
{
SharedMemoryTransmission();
}
}
Результаты работы.

Результат работы программы. Передача данных через «конвейер».

Лист
Лабораторная работа №4 ТОГУ, ИС-51, Храмцов А.А.
по Системному ПО 5
Результат работы программы. Передача данных через общую память.

5
Время в секундах

0
10 100 1000 10000 100000 1000000 10000000 100000000 1000000000

Объем передаваемых данных в байтах

«Конвейер». Зависимость времени передачи данных между процессами от объема


передаваемых данных в логарифмическом масштабе (по объему передаваемых данных).

Лист
Лабораторная работа №4 ТОГУ, ИС-51, Храмцов А.А.
по Системному ПО 6
8

6
Время в секундах
5

0
10 100 1000 10000 100000 1000000 10000000 100000000

Объем передаваемых данных в байтах

Общая память. Зависимость времени передачи данных между процессами от объема


передаваемых данных в логарифмическом масштабе (по объему передаваемых данных).

Лист
Лабораторная работа №4 ТОГУ, ИС-51, Храмцов А.А.
по Системному ПО 7