Помощь в написании студенческих работ
Антистрессовый сервис

Распределенная синхронизация процессов

КурсоваяПомощь в написанииУзнать стоимостьмоей работы

Интерфейс программы разработан с помощью Windows Forms. Интерфейс состоит из главного окна, на котором отображены данные о пользовательских настройках запуска процессов. При загрузке программы происходит заполнение окна конфигурационными данными. После загрузки, программа ищет «потомков» по сети и подключается к ним. Когда подключение установлено — программа проверяет, какой процесс следует… Читать ещё >

Распределенная синхронизация процессов (реферат, курсовая, диплом, контрольная)

Курсовая работа по дисциплине:

Операционные системы Распределенная синхронизация процессов

Введение

программа сетевой интерфейс При работе с данными на современных операционных системах остро стоит проблема в их синхронизации. Проблемы могут происходить, когда к одним и тем же данным получают доступ различные процессы. И даже не столько в случае одновременного изменения. Чтение данных в одном потоке после изменения их другим тоже может давать неверный результат в целом. Так же одной из проблем может являться уменьшение производительности работы в целом. Синхронизация — это некоторые дополнительные издержки.

Цель работы является разработка программы, создающая и запускающая несколько отдельных процессов в определённой последовательности. Информация о каждом запущенном процессе передаётся и принимается через сокеты UDP и записывается в файл.

В целом, задачей разработки являлось создание такого приложения, которое будет удалённо запускать в последовательности отдельные задачи.

В главе «Описание программ» подробно описаны теоретические особенности построения сетевого стека.

В главе «Тексты программ» находятся исходные коды на языке C# и файлы конфигурации процессов в формате INI файлов.

В главе «Выводы» даются результаты о проделанной работе.

Наиболее важными источниками знаний послужил сервис от Microsoft — MSDN, а также книга Гордеева — «Операционные системы».

Задание Создать процессы (отдельные задачи), которые выполняются в последовательности, определяемой графом запуска в соответствии с вариантом задания. Каждая дуга графа соответствует процессу, имя дуги — имя процесса. Вершины графа — точки синхронизации процессов.

Процессы после запуска находятся в ожидании завершения предшествующих им процессов. При выполнении выводят информацию (имя процесса, время запуска и окончания работы), передают управление другим процессам и завершаются. В процессах вводится небольшая временная задержка (несколько секунд) для того, чтобы было легче отследить соответствие запусков и окончаний процессов графу запуска. Для первоначального запуска набора процессов рекомендуется использовать командный файл.

Приём и передача информации о завершении процесса осуществляется через сокеты TCP или UDP. Фактически приём-передача этой информации выступает в роли средства распределённой синхронизации процессов в IP-сети.

Необходимо предусмотреть создание необходимого числа сокетов в каждой задаче и определить корректную нумерацию портов, чтобы обмен был возможен как на локальном компьютере (local host. localdomain) так и при запуске задач на компьютерах с разными IP-адресами в пределах локальной или глобальной TCP/IP-сети. Должна быть предусмотрена возможность изменения IP-адреса компьютера при запуске процесса (ввод из командной строки, файла и т. п.). При демонстрации курсовой работы часть процессов запускается на одном, а остальные — на другом (других) компьютере (компьютерах) ЛВС.

Операционная система — Windows или Linux. Система программирования — Visual C или GNU C. Возможен «гибридный» вариант реализации, когда часть процессов работает под управление ОС Linux, а оставшиеся — под ОС MS Windows. В последнем случае для отладки вне вычислительной сети имеет смысл использовать эмуляторы другой ОС (CYGWIN, WINE) или виртуальные машины.

Граф синхронизации процессов. Вариант #2

Рис. 1. Граф синхронизации процессов На графе отчётливо видно, что существует 11 дуг. Каждая дуга графа соответствует процессу. Вершины графа — точки синхронизации процессов. Имена процессов: a, b, c, d, e, f, g, h, i, m, n.

1. Описание программ

Программа работает под управлением Windows 32 бит. Написана на C# .NET 2.0. Данные в программу поступают по сетевому стеку UDP. Исходные данные лежат в отдельных INI файлах.

Программа состоит из модуля сервера и клиента. Клиент-сервер работает одновременно на одном компьютере. Во время включения программы, проверяется — есть ли у программы родитель — в случае нахождения происходит отправка сообщения и последующая работа. В остальном случае — программа слушает и в зависимости от принятых данных отправляет сообщения. Функции локального управления используются, главным образом, для выполнения подготовительных действий, необходимых для организации взаимодействия двух программ-партнёров.

1.1 Сокеты

В программе широко используются сокеты. В C# сокеты реализованы с помощью класса Socket. Класс Socket обеспечивает широкий набор методов и свойств для сетевых взаимодействий. Socket придерживается шаблона имён платформы .NET Framework для синхронный методов. Для протокола UDP, нет необходимости в отслеживании подключений. Метод Accept обрабатывает любые входящие запросы на подключение и возвращает объект Socket, который может использоваться для передачи данных с удалённого узла. Объект Socket используется для вызова метода Send или Receive. Метод Bind, обращается к Listen, к которому необходимо указать локальный IP-адрес или номер порта. Если требуется произвести подключение к прослушивающему узлу, используется метод Connect. Для обмена данными метод Send или Receive. Когда приём и отправка данных завершены, используется метод Shutdown для того, чтобы отключить объект Socket. После вызова метода Shutdown происходит обращение к методу Close, чтобы освободить все связанные с объектом Socket ресурсы.

Процесс в Windows состоит из следующих компонентов:

· Структура данных, содержащая всю информацию о процессе, в том числе список открытых дескрипторов различных системных ресурсов, уникальный идентификатор процесса, различную статистическую информацию и т. д.;

· Адресное пространство — диапазон адресов виртуальной памяти, которым может пользоваться процесс;

· Исполняемая программа и данные, проецируемые на виртуальное адресное пространство процесса.

Создание Win32 процесса осуществляется вызовом одной из таких функций, как CreateProcess, CreateProcessAsUser (для Win NT/2000) и CreateProcessWithLogonW (начиная с Win2000) и происходит в несколько этапов:

· Открывается файл образа (EXE), который будет выполняться в процессе.

· Если исполняемый файл не является Win32 приложением, то ищется образ поддержки (support image) для запуска этой программы. Например, если запускается cmd.exe.

Процесс завершается если:

· Входная функция первичного потока возвратила управление.

· Один из потоков процесса вызвал функцию ExitProcess.

· Поток другого процесса вызвал функцию TerminateProcess.

· Когда процесс завершается, все Userи GDI-объекты, созданные процессом, уничтожаются, объекты ядра закрываются (если их не использует другой процесс), адресное пространство процесса уничтожается.

1.2 Процессы

Процесс — это объединение нескольких потоков. А объединяет эти потоки единое виртуальное адресное пространство. В этом пространстве размещаются код и данные приложения (обычно это один exe и несколько dll-модулей). Именно единство этого пространства и делает обмен данными между потоками приложения предельно простым. Наоборот, адресные пространства различных процессов независимы и отделены друг от друга (хотя, используя проекции файла в память (memory mapped file), можно создать область памяти, которая будет доступна совместно нескольким процессам). Таким образом, процесс — это несколько потоков (как минимум один) плюс единое виртуальное адресное пространство. Поскольку все потоки процесса работают в едином адресном пространстве, обмен данными между ними крайне прост, однако при этом требуется согласовывать их работу над совместными данными. Собственно, под термином «синхронизация», как правило, имеют в виду именно согласование работы потоков, принадлежащих одному процессу. Этому и будут посвящены следующие части данной статьи. Хотя некоторые из описанных далее приёмов можно использовать и для синхронизации потоков принадлежащих разным процессам, в основном согласование их работы связано с «механизмами взаимосвязи процессов» (inter-process communications, IPC). Действительно, трудно представить ситуацию, когда нам потребовалось бы согласовывать движение потоков без необходимости обмена данными между ними. А для этого, если потоки работают в разных адресных пространствах, требуются специальные механизмы, носящие обобщённое название IPC (проекции файлов в память — один из них). Процесс — это набор потоков, работающих в едином адресном пространстве. Само по себе, адресное пространство без потоков смысла не имеет. Поэтому процесс считается завершённым, как только завершатся все его потоки.

2. Тексты программ

Интерфейс программы разработан с помощью Windows Forms. Интерфейс состоит из главного окна, на котором отображены данные о пользовательских настройках запуска процессов. При загрузке программы происходит заполнение окна конфигурационными данными. После загрузки, программа ищет «потомков» по сети и подключается к ним. Когда подключение установлено — программа проверяет, какой процесс следует запустить, в случае нахождения данных о процессе — запускает его. После завершения процесса — выполнившая программа останавливается. А «родителем» становится программа, которая приняла все данные. «Родитель» начинает процесс поиска своих «потомков». Интерфейс достаточно прост. И не требует от пользователя каких-либо действий, кроме правки конфигурационного файла.

Рис. 2. Скриншот работы 4 процессов на локальном компьютере

2.1 Исходный код

class WriteLog {

public static bool Write (string message) {

try {

const string url = @" \fsStudy_ПО08temp.txt" ;

var text = System.IO.File.AppendText (url);

text.WriteLine (message);

text.Close ();

}

catch {

return false;

} return true;

}

}

internal class Client {

private readonly string Ip;

private readonly int Port;

private readonly string Processname;

private TcpClient _client;

public Client (string ip, int port, string processname) {

Ip = ip;

Port = port;

Processname = processname;

if (SendData ()) {

FormClient.Msg («Данные успешно отправлены!»);

} // Теперь подключаться к потомкам

}

private bool SendData () {

_client = new TcpClient ();

bool flag = true;

try {

_client.Connect (Ip, Port);

byte[] mas = Encoding. UTF8.GetBytes (Processname);

_client.Client.Send (mas);

}

catch {

flag = false;

} return flag;

}

}

public partial class FormClient: Form {

private static readonly string Path = Environment. CurrentDirectory; // текущая директория

#region Списки

private List _childProcessname;

private List _childsIp;

private List _childsPort;

private List _parentProcessname;

private List _serverPort;

private List _serverProcessname;

#endregion

public FormClient () {

InitializeComponent ();

GetInfoFromINIFile ();

var cr = new Thread (OpenPort);

cr.Start ();

//Если родителей нет — подключаюсь к потомкам

if (_parentProcessname.Count == 0 && _serverProcessname.Count > 0) {

string processname = _serverProcessname[0];

const string ip = «127.0.0.1» ;

int port = int. Parse (_serverPort[0]);

new Client (ip, port, processname); //а также выполняем главные процесс А

ConnectToChild ();

}

}

public void OpenPort () {

foreach (string t in _serverPort) {

if (t == «») return;

try {

int port = Convert. ToInt16(t);

//Если родители есть то открываем порт

if (_parentProcessname.Count ≠ 0) {

Msg («Открываю порт «+ port + «для подключения родителей»);

new Servak (port);

}

}

catch {

Msg («Проблема при открытие порта»);

}

}

}

public void ConnectToChild () {

Msg («ищем потомков…»);

//Если потомки есть

if (_childProcessname.Count ≠ 0) {

for (int i = 0; i < _childsPort.Count; i++) {

int port = Convert. ToInt16(_childsPort[i]);

string ip = _childsIp[i];

string processname = _childProcessname[i];

Msg («подключаюсь к потомку «+ processname); // Подключаемся к серверу по serverPort

try {

new Client (ip, port, processname); //подключаемся к потомку

}

catch {

Msg (string.Format («Подключиться к потомку {0} не удалось», processname));

}

}

}

else {

Msg («Потомков нет.»);

}

}

public static void Msg (string mesg) {

if (!WriteLog.Write (mesg)) {

MessageBox.Show («Произошла проблема с записью»);

}

}

private void GetInfoFromINIFile () {

FileInfo[] directorypath = new DirectoryInfo (Path).GetFiles ();

//Заполнение списков

_serverProcessname = new List ();

_serverPort = new List ();

_parentProcessname = new List ();

_childProcessname = new List ();

_childsIp = new List ();

_childsPort = new List ();

//инфо об файлах

foreach (FileInfo info in directorypath) {

string fullname = info. FullName;

var temp = new IniFile (fullname);

string[] readText = File. ReadAllLines (fullname); //временный, зранит все записи

//Читаем все строчки

foreach (string s in readText) {

if (s == «»)

continue;

if (Regex.IsMatch (s, «Server»)) { _serverProcessname.Add (temp.IniReadValue («Server», «Processname»)); _serverPort.Add (temp.IniReadValue («Server», «Port»));

}

//Если найден Parent — добавляем (учитывая что есть 1, 2, …)

else if (Regex.IsMatch (s, «Parent»)){

string parentS = s. Replace («[», «»).Replace («]», «»);

_parentProcessname.Add (temp.IniReadValue (parentS, «Processname»));

}

//то же самое только с Child

else if (Regex.IsMatch (s, «Child»)){

string childS = s. Replace («[», «»).Replace («]», «»);

//Проверка на UTF-8. Глюк возникает, в «s» вводится какая-то очень длинная

if (s.Length > 50)

break; _childProcessname.Add (temp.IniReadValue (childS, «Processname»));

_childsIp.Add (temp.IniReadValue (childS, «Ip»));

_childsPort.Add (temp.IniReadValue (childS, «Port»));

}

}

}

GetText ();

}

private void AddText (string text) {

if (text ≠ «»)

tbxText.Text = tbxText. Text + Environment. NewLine + text;

}

private void GetText () {

AddText (Environment.NewLine + «Серверы»);

foreach (string server in _serverProcessname) {

AddText (server);

}

AddText (Environment.NewLine + «Айпи Серверов «);

foreach (string servPort in _serverPort) {

AddText (servPort);

}

AddText (Environment.NewLine + «Родители»);

foreach (string parent in _parentProcessname) {

AddText (parent);

}

AddText (Environment.NewLine + «Потомки»);

foreach (string child in _childProcessname) {

AddText (child);

}

AddText (Environment.NewLine + «Айпи детей»);

foreach (string s in _childsIp) {

AddText (s);

}

AddText (Environment.NewLine + «Порты детей»);

foreach (string s in _childsPort) {

AddText (s);

}

}

}

public class IniFile{

public string path;

/// Конструктор класса

/// Путь к INI-файлу

public IniFile (string INIPath) {

path = INIPath;

}

[DllImport («kernel32»)]

private static extern long WritePrivateProfileString (string section, string key, string val, string filePath);

[DllImport («kernel32»)]

private static extern int GetPrivateProfileString (string section, string key, string def, StringBuilder retVal, int size, string filePath);

public void IniWriteValue (string Section, string Key, string Value) {

WritePrivateProfileString (Section, Key, Value, path);

}

public string IniReadValue (string section, string key) {

var temp = new StringBuilder (255);

GetPrivateProfileString (section, key, «», temp,

255, path);

return temp. ToString ();

}

}

internal class Processes {

private static void SendData (object data) {

FormClient.Msg («выполняется процесс «+ data);

var fp = new FormPotok {Text = data. ToString ()};

fp.Show ();

for (var millisecondsTimeout = 1; millisecondsTimeout < 100; millisecondsTimeout++) {

fp.progBar.Value = millisecondsTimeout;

Thread.Sleep (millisecondsTimeout);

}

FormClient.Msg («Процесс «+ data + «выполнен»);

new FormClient ().ConnectToChild ();//Теперь передачу на потомков

}

public static void StartPotoks (string name) {

new Thread (SendData).Start (name);

}

}

class Servak {

public Servak (int port) {

FormClient.Msg («Ожидаем запрос к подключению»);

IPEndPoint ipep = new IPEndPoint (IPAddress.Any, port);

Socket newsock = new Socket (AddressFamily.InterNetwork,

SocketType.Stream, ProtocolType. IP);

newsock.Bind (ipep);

newsock.Listen (10);

FormClient.Msg («родитель подключен…»);

Socket client = newsock. Accept ();

var data = new byte[1024];

var recv = client. Receive (data);

string RecvString = Encoding.ASCII.GetString (data, 0, recv);

Processes.StartPotoks (RecvString);

}

}

2.2 Конфигурационный файл

Процесс a

[Server]

Port = 8881

Processname = a

[Child1]

Ip = 127.0.0.1

Port = 8883

Processname = c

[Child2]

Ip = 127.0.0.1

Port = 8884

Processname = d

[Child3]

Ip = 127.0.0.1

Port = 8885

Processname = e

Процесс b

[Server]

Port = 8882

Processname = b

[Child1]

Ip = 127.0.0.1

Port = 8889

Processname = i

[Child2]

Ip = 127.0.0.1

Port = 8888

Processname = h

[Child3]

Ip = 127.0.0.1

Port = 8887

Processname = g

Процесс c

[Server]

Port = 8883

Processname = c

[Parent1]

Processname = a

[Child1]

Ip = 127.0.0.1

Port = 8889

Processname = i

[Child2]

Ip = 127.0.0.1

Port = 8888

Processname = h

[Child3]

Port = 8887

Ip = 127.0.0.1

Processname = g

Процесс n

[Server]

Port = 8892

Processname = n

[Parent1]

Processname = i

[Parent2]

Processname = k

[Parent3]

Processname = m

Процесс d

[Server]

Port = 8884

Processname = d

[Parent1]

Processname = a

[Child1]

Ip = 127.0.0.1

Port = 8886

Processname = f

Процесс e

[Server]

Port = 8885

Processname = e

[Parent1]

Processname = a

[Child1]

Ip = 127.0.0.1

Port = 8890

Processname = k

[Child2]

Ip = 127.0.0.1

Port = 8891

Processname = m

Процесс f

[Server]

Port = 8886

Processname = f

[Parent1]

Processname = d

[Child1]

Ip = 127.0.0.1

Port = 8890

Processname = k

[Child2]

Ip = 127.0.0.1

Port = 8891

Processname = m

Процесс h

[Server]

Port = 8888

Processname = h

[Parent1]

Processname = c

[Parent2]

Processname = b

[Child1]

Ip = 127.0.0.1

Port = 8890

Processname = k

[Child2]

Ip = 127.0.0.1

Port = 8891

Processname = m

Процесс g

[Server]

Port = 8887

Processname = g

[Parent1]

Processname = b

[Parent2]

Processname = c

[Child1]

Ip = 127.0.0.1

Port = 8890

Processname = k

[Child2]

Ip = 127.0.0.1

Port = 8891

Processname = m

Процесс k

[Server]

Port = 8890

Processname = k

[Parent1]

Processname = h

[Parent2]

Processname = g

[Parent3]

Processname = f

[Parent4]

Processname = e

[Child1]

Ip = 127.0.0.1

Port = 8892

Processname = n

Процесс i

[Server]

Port = 8889

Processname = i

[Parent1]

Processname = b

[Parent2]

Processname = c

[Child1]

Ip = 127.0.0.1

Port = 8892

Processname = n

Процесс m

[Server]

Port = 8891

Processname = m

[Parent1]

Processname = h

[Parent2]

Processname = g

[Parent3]

Processname = f

[Parent4]

Processname = e

[Child1]

Ip = 127.0.0.1

Port = 8892

Processname = n

2.3 Результаты тестирования

Открываю порт 8883 для подключения родителей Ожидаем запрос к подключению родитель подключен…

Открываю порт 8889 для подключения родителей Ожидаем запрос к подключению родитель подключен…

ищем потомков…

подключаюсь к потомку c

Данные успешно отправлены!

выполняется процесс c

Процесс c выполнен ищем потомков…

подключаюсь к потомку i

Данные успешно отправлены!

подключаюсь к потомку h

Данные успешно отправлены!

выполняется процесс i

выполняется процесс h

Проблема при открытие порта Процесс i выполнен Открываю порт 8889 для подключения родителей Ожидаем запрос к подключению Проблема при открытие порта ищем потомков…

потомков нет.

Процесс h выполнен Открываю порт 8888 для подключения родителей Ожидаем запрос к подключению Проблема при открытие порта ищем потомков…

потомков нет.

Заключение

Благодаря использованию встроенных средств языка C# удалось создать проект, использующий сетевой стек и сетевые функции Windows. Что в конечном итоге сделало возможным создание программы, которая способна пересылать данные на удалённый компьютер. Следующим этапом стало создание удобного интерфейса. Интерфейс построен с использованием Windows Forms

В программе предусмотрен обмен как на локальном компьютере, так и при запуске на компьютерах с разными IP-адресами в пределах локальной или глобальной TCP/IP-сети. Предусмотрена возможность изменения IP-адреса компьютера при запуске процесса, посредством правки файла конфигурации.

«Гибридный» вариант реализации, когда часть процессов работает под управление ОС Linux, а оставшиеся — под ОС MS Windows не предусмотрена в силу ограничения работы .net framework на первом. Отладка производилась без применения виртуальных машин.

1. Гордеев А. В. Операционные системы СПб. Питер, 2004.

2. Рихтер Д. Ж. CLR via C#. Программирование на платформе.NET Framework 2.0 на языке С#. Мастер-класс. СПб. Питер, 2007

3. MSDN

Process (http://msdn.microsoft.com/ru-ru/library/system.diagnostics.process.aspx)

Socket (http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.beginreceive%28VS.80%29.aspx)

4. Wikipedia

UDP (https://ru.wikipedia.org/wiki/UDP)

TCP/IP (https://ru.wikipedia.org/wiki/TCP/IP)

5. Форум stackoverflow.com

Показать весь текст
Заполнить форму текущей работой