ЛР-4 ОС
.docx
ФЕДЕРАЛЬНОЕ АГЕНТСТВО СВЯЗИ
Ордена Трудового Красного Знамени
федеральное государственное бюджетное образовательное учреждение
высшего образования
Московский технический университет связи и информатики
----------------------------------------------------------------------------------------------
Кафедра Математической кибернетики и информационных технологий
ЛАБОРАТОРНАЯ РАБОТА № 4
по дисциплине
ОПЕРАЦИОННЫЕ СИСТЕМЫ
«Реализация обмена данными между процессами»
Выполнил:
студент Гончарова Екатерина
группа БФИ1601
Проверил:
Королькова Т.В.
ст. пр. кафедры МКиИТ
Дата 13.11.2018
Москва 2018
Название работы: Реализация обмена данными между процессами.
Цель работы: Изучение набора средств коммуникации процессов в Windows NT. Получение практических навыков по использованию Win32 API для программирования механизмов межпроцессного взаимодействия.
Задание: Программа, выполняющая с помощью ВСЕХ перечисленных механизмов межпроцессного взаимодействия (отображение файлов, почтовые ящики, каналы)
Почтовые ящики.
Исходный код:
Сервер:
#include "pch.h"
#include <iostream>
#include <windows.h>
#include<cstdlib>
#include<ctime>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
using namespace std;
HANDLE hSlot;
LPCTSTR SlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");
BOOL ReadSlot()
{
DWORD cbMessage, cMessage, cbRead;
BOOL fResult;
LPTSTR lpszBuffer;
TCHAR achID[80];
DWORD cAllMessages;
HANDLE hEvent;
OVERLAPPED ov;
cbMessage = cMessage = cbRead = 0;
hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("ExampleSlot"));
if (NULL == hEvent)
return FALSE;
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = hEvent;
fResult = GetMailslotInfo(hSlot, // mailslot handle
(LPDWORD)NULL, // no maximum message size
&cbMessage, // size of next message
&cMessage, // number of messages
(LPDWORD)NULL); // no read time-out
if (!fResult)
{
printf("GetMailslotInfo failed with %d.\n", GetLastError());
return FALSE;
}
if (cbMessage == MAILSLOT_NO_MESSAGE)
{
printf("Waiting for a message...\n");
return TRUE;
}
cAllMessages = cMessage;
while (cMessage != 0) // retrieve all messages
{
// Create a message-number string.
StringCchPrintf((LPTSTR)achID,
80,
TEXT("\nMessage #%d of %d\n"),
cAllMessages - cMessage + 1,
cAllMessages);
// Allocate memory for the message.
lpszBuffer = (LPTSTR)GlobalAlloc(GPTR,
lstrlen((LPTSTR)achID) * sizeof(TCHAR) + cbMessage);
if (NULL == lpszBuffer)
return FALSE;
lpszBuffer[0] = '\0';
fResult = ReadFile(hSlot,
lpszBuffer,
cbMessage,
&cbRead,
&ov);
if (!fResult)
{
printf("ReadFile failed with %d.\n", GetLastError());
GlobalFree((HGLOBAL)lpszBuffer);
return FALSE;
}
// Concatenate the message and the message-number string.
StringCbCat(lpszBuffer,
lstrlen((LPTSTR)achID) * sizeof(TCHAR) + cbMessage,
(LPTSTR)achID);
// Display the message.
_tprintf(TEXT("Contents of the mailslot: %s\n"), lpszBuffer);
//Освобождает pазблокиpованный блок глобальной памяти и делает недействительным его описатель.
GlobalFree((HGLOBAL)lpszBuffer);
fResult = GetMailslotInfo(hSlot, // mailslot handle
(LPDWORD)NULL, // no maximum message size
&cbMessage, // size of next message
&cMessage, // number of messages
(LPDWORD)NULL); // no read time-out
if (!fResult)
{
printf("GetMailslotInfo failed (%d)\n", GetLastError());
return FALSE;
}
}
CloseHandle(hEvent);
return TRUE;
}
BOOL WINAPI MakeSlot(LPCTSTR lpszSlotName)
{
hSlot = CreateMailslot(lpszSlotName,
0, // no maximum message size
MAILSLOT_WAIT_FOREVER, // no time-out for operations
(LPSECURITY_ATTRIBUTES)NULL); // default security
if (hSlot == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot failed with %d\n", GetLastError());
return FALSE;
}
return TRUE;
}
int main()
{
MakeSlot(SlotName);
while (TRUE)
{
ReadSlot();
Sleep(3000);
}
return 0;
}
Клиент:
#include "pch.h"
#include <iostream>
#include <windows.h>
#include<cstdlib>
#include<ctime>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <windows.h>
#include <stdio.h>
LPCTSTR SlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");
BOOL WriteSlot(HANDLE hSlot, LPTSTR lpszMessage)
{
BOOL fResult;
DWORD cbWritten;
fResult = WriteFile(hSlot,
lpszMessage,
(DWORD)(lstrlen(lpszMessage) + 1) * sizeof(TCHAR),
&cbWritten,
(LPOVERLAPPED)NULL);
if (!fResult)
{
printf("WriteFile failed with %d.\n", GetLastError());
return FALSE;
}
printf("Slot written to successfully.\n");
return TRUE;
}
int main()
{
HANDLE hFile;
hFile = CreateFile(SlotName,
GENERIC_WRITE,
FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with %d.\n", GetLastError());
return FALSE;
}
LPCTSTR text1 = TEXT("Message one for mailslot.");
LPCTSTR text2 = TEXT("Message two for mailslot.");
LPCTSTR text3 = TEXT("Message three for mailslot.");
WriteSlot(hFile, LPTSTR(text1));
Sleep(3000);
WriteSlot(hFile, LPTSTR(text2));
Sleep(3000);
WriteSlot(hFile, LPTSTR(text3));
printf("Complete!");
CloseHandle(hFile);
return TRUE;
}
Рисунок 1 - результат работы с почтовыми ящиками
Каналы.
Исходный код:
Сервер:
#include "pch.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#include<cstdlib>
#include<ctime>
#include <strsafe.h>
using namespace std;
#include <windows.h>
#include <stdio.h>
#include <conio.h>
int main()
{
// Флаг успешного создания канала
BOOL fConnected;
// Идентификатор канала Pipe
HANDLE hNamedPipe;
// Имя создаваемого канала Pipe
LPCTSTR lpszPipeName = TEXT("\\\\.\\pipe\\$MyPipe$");
// Буфер для передачи данных через канал
char szBuf[512];
// Количество байт данных, принятых через канал
DWORD cbRead;
// Количество байт данных, переданных через канал
DWORD cbWritten;
// Создаем канал Pipe, имеющий имя lpszPipeName
hNamedPipe = CreateNamedPipe(
lpszPipeName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
512, 512, 5000, NULL);
// Если возникла ошибка, выводим ее код и зваершаем
// работу приложения
if (hNamedPipe == INVALID_HANDLE_VALUE)
{
fprintf(stdout, "CreateNamedPipe: Error %ld\n",
GetLastError());
_getch();
return 0;
}
// Выводим сообщение о начале процесса создания канала
fprintf(stdout, "Waiting for connect...\n");
// Ожидаем соединения со стороны клиента
fConnected = ConnectNamedPipe(hNamedPipe, NULL);
// При возникновении ошибки выводим ее код
if (!fConnected)
{
switch (GetLastError())
{
case ERROR_NO_DATA:
fprintf(stdout, "ConnectNamedPipe: ERROR_NO_DATA");
_getch();
CloseHandle(hNamedPipe);
return 0;
break;
case ERROR_PIPE_CONNECTED:
fprintf(stdout,
"ConnectNamedPipe: ERROR_PIPE_CONNECTED");
_getch();
CloseHandle(hNamedPipe);
return 0;
break;
case ERROR_PIPE_LISTENING:
fprintf(stdout,
"ConnectNamedPipe: ERROR_PIPE_LISTENING");
_getch();
CloseHandle(hNamedPipe);
return 0;
break;
case ERROR_CALL_NOT_IMPLEMENTED:
fprintf(stdout,
"ConnectNamedPipe: ERROR_CALL_NOT_IMPLEMENTED");
_getch();
CloseHandle(hNamedPipe);
return 0;
break;
default:
fprintf(stdout, "ConnectNamedPipe: Error %ld\n",
GetLastError());
_getch();
CloseHandle(hNamedPipe);
return 0;
break;
}
CloseHandle(hNamedPipe);
_getch();
return 0;
}
// Выводим сообщение об успешном создании канала
fprintf(stdout, "\nConnected. Waiting for command...\n");
// Цикл получения команд через канал
while (1)
{
// Получаем очередную команду через канал Pipe
if (ReadFile(hNamedPipe, szBuf, 512, &cbRead, NULL))
{
// Посылаем эту команду обратно клиентскому
// приложению
if (!WriteFile(hNamedPipe, szBuf, strlen(szBuf) + 1,
&cbWritten, NULL))
break;
// Выводим принятую команду на консоль
printf("Received: <%s>\n", szBuf);
// Если пришла команда "exit",
// завершаем работу приложения
if (!strcmp(szBuf, "exit"))
break;
}
else
{
fprintf(stdout, "ReadFile: Error %ld\n",
GetLastError());
_getch();
break;
}
}
CloseHandle(hNamedPipe);
return 0;
}
Клиент:
#include "pch.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <strsafe.h>
using namespace std;
int main() {
// Идентификатор канала Pipe
HANDLE hNamedPipe;
// Количество байт, переданных через канал
DWORD cbWritten;
// Количество байт, принятых через канал
DWORD cbRead;
// Буфер для передачи данных
char szBuf[256];
LPCTSTR szPipeName = TEXT("\\\\.\\pipe\\$MyPipe$");
// Создаем канал с процессом PIPES
hNamedPipe = CreateFile(
szPipeName, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
// Если возникла ошибка, выводим ее код и
// завершаем работу приложения
if (hNamedPipe == INVALID_HANDLE_VALUE)
{
fprintf(stdout, "CreateFile: Error %ld\n",
GetLastError());
_getch();
return 0;
}
// Выводим сообщение о создании канала
fprintf(stdout, "\nConnected. Type 'exit' to terminate\n");
// Цикл обмена данными с серверным процессом
while (1)
{
// Выводим приглашение для ввода команды
printf("cmd>");
// Вводим текстовую строку
cin >> szBuf;
// Передаем введенную строку серверному процессу
// в качестве команды
if (!WriteFile(hNamedPipe, szBuf, strlen(szBuf) + 1,
&cbWritten, NULL))
break;
// Получаем эту же команду обратно от сервера
if (ReadFile(hNamedPipe, szBuf, 512, &cbRead, NULL))
printf("Received back: <%s>\n", szBuf);
// Если произошла ошибка, выводим ее код и
// завершаем работу приложения
else
{
fprintf(stdout, "ReadFile: Error %ld\n",
GetLastError());
_getch();
break;
}
// В ответ на команду "exit" завершаем цикл
// обмена данными с серверным процессом
if (!strcmp(szBuf, "exit"))
break;
}
// Закрываем идентификатор канала
CloseHandle(hNamedPipe);
return 0;
}
Рисунок 2 - результат передачи данных через каналы
Файловое отображение.
Исходный код:
#include "pch.h"
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <Windows.h>
#include <cstring>
struct SharedData {
int sch = 0;
char mas[16];
};
HANDLE mutex;
HANDLE mapping;
using namespace std;
int main() {
DWORD dwBytesWritten = 0;
HANDLE hFile = CreateFile(TEXT("test1.txt"), // name of the write
GENERIC_WRITE | GENERIC_READ, // open for reading and writing
FILE_SHARE_WRITE | FILE_SHARE_READ, // share for reading and writing
NULL, // default security
OPEN_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
mapping = CreateFileMappingA(hFile, nullptr, PAGE_READWRITE, 0, sizeof(SharedData), "first1");
unique_ptr<SharedData, decltype(&UnmapViewOfFile)> data(
(SharedData*)MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0),
UnmapViewOfFile);
mutex = OpenMutexA(MUTEX_ALL_ACCESS, TRUE, "first");
while (mutex == NULL) {
mutex = CreateMutexA(NULL, FALSE, "first");
}
cout << "hFile:" << hFile << endl;
cout << "mapping:" << mapping << endl;
cout << "mutex:" << mutex << endl;
DWORD dwBytesToWrite = 13;
//system("pause");
thread user_input_thread([&] {
WaitForSingleObject(mutex, INFINITE);
for (int i = 0; i < 4; i++) {
data->mas[data->sch] = '9';
cout << "mas[" << data->sch << "]= " << data->mas[data->sch] << " ";
WriteFile(
hFile, // open file handle
(LPCVOID)data->mas[data->sch], // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL);
Sleep(500);
data->sch++;
}
ReleaseMutex(mutex);
});
user_input_thread.join();
system("pause");
CloseHandle(hFile);
}
>>>>>>>>>>>
Следующая программа:
#include "pch.h"
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <Windows.h>
#include <cstring>
struct SharedData {
int sch = 0;
char mas[16];
};
HANDLE mutex;
HANDLE mapping;
using namespace std;
int main() {
DWORD dwBytesWritten = 0;
HANDLE hFile = CreateFile(TEXT("test1.txt"), // name of the write
GENERIC_WRITE | GENERIC_READ, // open for reading and writing
FILE_SHARE_WRITE | FILE_SHARE_READ, // share for reading and writing
NULL, // default security
OPEN_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
mapping = CreateFileMappingA(hFile, nullptr, PAGE_READWRITE, 0, sizeof(SharedData), "first1");
unique_ptr<SharedData, decltype(&UnmapViewOfFile)> data(
(SharedData*)MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0),
UnmapViewOfFile);
mutex = OpenMutexA(MUTEX_ALL_ACCESS, TRUE, "first");
if (mutex == NULL) {
mutex = CreateMutexA(NULL, FALSE, "first");
}
cout << "hFile:" << hFile << endl;
cout << "mapping:" << mapping << endl;
cout << "mutex:" << mutex << endl;
DWORD dwBytesToWrite = 13;
//system("pause");
thread user_input_thread([&] {
WaitForSingleObject(mutex, INFINITE);
for (int i = 0; i < 4; i++) {
data->mas[data->sch] = '3';
cout << "mas[" << data->sch << "]= " << data->mas[data->sch] << " ";
WriteFile(
hFile, // open file handle
(LPCVOID)data->mas[data->sch], // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL);
Sleep(500);
data->sch++;
}
ReleaseMutex(mutex);
});
user_input_thread.join();
system("pause");
CloseHandle(hFile);
}
Рисунок 3 - результат записи в файл