Распределенная синхронизация процессов
Разработка проекта с помощью встроенных средств языка C#, на базе сетевого стека и сетевых функций Windows. Специфика создания удобного интерфейса программы с использованием Windows Forms, которая способна пересылать данные на удалённый компьютер.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 16.06.2013 |
Размер файла | 162,6 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
25
Размещено на http://www.allbest.ru/
Курсовая работа
по дисциплине:
Операционные системы
Распределенная синхронизация процессов
Введение
программа сетевой интерфейс
При работе с данными на современных операционных системах остро стоит проблема в их синхронизации. Проблемы могут происходить, когда к одним и тем же данным получают доступ различные процессы. И даже не столько в случае одновременного изменения. Чтение данных в одном потоке после изменения их другим тоже может давать неверный результат в целом. Так же одной из проблем может являться уменьшение производительности работы в целом. Синхронизация - это некоторые дополнительные издержки.
Цель работы является разработка программы, создающая и запускающая несколько отдельных процессов в определённой последовательности. Информация о каждом запущенном процессе передаётся и принимается через сокеты 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
Размещено на http://www.allbest.ru/
25
Размещено на http://www.allbest.ru/
Рис. 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 = @"\\fs\Study\_\ПО08\temp.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<string> _childProcessname;
private List<string> _childsIp;
private List<string> _childsPort;
private List<string> _parentProcessname;
private List<string> _serverPort;
private List<string> _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<string>();
_serverPort = new List<string>();
_parentProcessname = new List<string>();
_childProcessname = new List<string>();
_childsIp = new List<string>();
_childsPort = new List<string>();
//инфо об файлах
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;
/// <summary>
/// Конструктор класса
/// </summary>
/// <PARAM name="INIPath">Путь к INI-файлу</PARAM>
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
Размещено на Allbest.ru
Подобные документы
Описание платформы NET Framework. База данных Microsoft Access. Разработка Windows приложения. Модель программирования Windows Forms. Функциональное назначение программы. Входные и выходные данные. Требования к техническому и программному обеспечению.
курсовая работа [2,2 M], добавлен 15.03.2015Программирование в операционной системе Windows. Работа с потоками и процессами ОС. Методы их создания. Основы вызова API-функций. Пример создания диалогового окна без использования файла ресурсов. Разработка программы с помощью 32-битного ассемблера.
курсовая работа [107,6 K], добавлен 18.05.2014Сведения об окружности, ее радиус и площадь. Разработка программы для вычисления площади круга и длины окружности по заданному радиусу с использованием Windows.Forms-приложений. Пошаговая инструкция; описание главного окна, код, примеры работы программы.
курсовая работа [818,6 K], добавлен 14.09.2014Общие положения по программированию в интерфейсе Windows Forms. Среда разработки MicrosoftVisualStudio, ее главные особенности и характеристика. Создание эмулятора пункта меню Microsoft Office Word "Формат-Шрифт" с использованием интерфейса Windows Forms.
курсовая работа [3,4 M], добавлен 26.01.2013Основы программирования на 32-битном Ассемблере, разработка с его помощью программы, демонстрирующей работу одного из разделов ОС Windоws. Описание используемых АРI-функций как интерфейса программирования приложений. Листинг программы, результаты работы.
курсовая работа [164,5 K], добавлен 18.05.2014Техника создания графики при помощи API функций, экспортируемых библиотекой GDI32.DLL. Разработка на языке программирования С++ в среде программирования Microsoft Visual C++ программы для отображения часов реального времени в цифровом и аналоговом виде.
курсовая работа [2,8 M], добавлен 27.01.2010Характеристика операционной системы. История развития Windows. Сравнительная характеристика версий Windows. Элементы и инструменты Windows XP. Прикладные программы в Windows XP. Работа настольных и портативных компьютеров под управлением Windows.
доклад [19,1 K], добавлен 16.10.2011Разработка программного приложения Windows Forms для работы с базой данных на языке высокого уровня в автономном режиме с использованием ADO.NET. Создание консольных приложений (варианты метода Main), выполнение запросов к SQL серверу и листинг программ.
курсовая работа [2,4 M], добавлен 16.06.2014Интерфейс API, реализация функций API на уровне ОС, системы программирования и с помощью внешних библиотек. Характеристики сетевого интерфейса прикладного программирования Winsock, особенности его применения в операционных системах UNIX и Windows.
контрольная работа [74,2 K], добавлен 04.06.2015Создание программы "MP3 Player", воспроизводящей аудио файлы формата MP3 для работы в операционной системе Windows с использованием языка программирования Delphi. Разработка интерфейса, алгоритма и документации к разработанному программному продукту.
курсовая работа [625,0 K], добавлен 18.07.2012