Академический Документы
Профессиональный Документы
Культура Документы
Задание
Напишите программу, которая измеряет скорость передачи данных между процессами
используя два вида межпроцессных коммуникаций – неименованные каналы и сегменты общей
памяти. Передаваемые данные должны быть представлены в виде произвольного набора
символов.
Используйте свою программу для исследования скорости передачи пакетов данных
различных размеров – от нескольких байт до нескольких десятков мегабайт. Результаты
измерений представьте в виде графиков – зависимость времени передачи данных между
процессами от объема передаваемых данных для неименованных каналов и сегментов общей
памяти. Графики представьте в логарифмическом масштабе (по объему передаваемых данных).
В случае необходимости, для синхронизации процессов (потоков) используйте либо
семафоры (функции 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>
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++;
}
//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
}
//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);
}
}
Лист
Лабораторная работа №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