Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Об общении программ  (Прочитано 8951 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Migmile
Помогающий

ru
Offline Offline

« : 05-01-2004 09:03 » 

Имеется важная задача task1.exe, выолняющаяся непрерывно. В случае ее неверной работы необходимо ее перезапустить. Для этого можно создать некий service, работающий на той-же машине, который периодически контролирует состояние task1.exe и при определеннных условиях перезапускает task1.exe. Какой метод контроля использовать для того, чтобы наименьшим образом отвлекать task1.exe от основной работы? Мне приходят в голову socket (UDP), Messages, createremotethread или любой другой механизм внедрения в процесс task1.exe, расSHAREную память (то-бишь флаги), общие файлы, и др.
Может-ли кто-нибудь отсечь или добавить, короче говоря, подсказать, что лучше, а что хуже:)
Записан
Migmile
Помогающий

ru
Offline Offline

« Ответ #1 : 05-01-2004 10:29 » 

PS.
Всех с Новым Годом Отлично
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #2 : 05-01-2004 11:26 » 

Migmile, это называется WatchDog.
Способ организации зависит от самого типа задачи выполняемой  task1.exe.

Единственное, что посоветую - запускать не в виде сервиса, а виде отдельного процесса просто так как сервис сам по себе дело сложное, а вот простой процесс - вполне простое.

При работе с уже имеющимися сокетами - можно добавить сокет для проверки и связи...
В общем метод проверки не должен тормозить и делать что-то сверхестественное, методы можно комбинировать, скажем открытие сокета и его закрытие - есть сигнал к заполнению памяти. Скажем WatchDog открывает сокет  и этим сообщает основной программе, что пора заполнить структуру данными, после этого, закрытие сокета не по тайм-ауту программой скажет  WatchDog процессу, что память заполнена новыми данными и можно их вычитать.
Записан

А птичку нашу прошу не обижать!!!
Lex
Специалист

ru
Offline Offline

WWW
« Ответ #3 : 05-01-2004 12:03 » 

Мне кажется правильнее сделать подобие аппаратных WatchDog'ов в микроконтроллерах. Т.е. ты создаешь отдельный процесс в котором запускается таймер. И товя оснавная программа переодически должна сбрасывать этот таймер. Если таймер досчитал до какого-то определенного значения и не сбросился, значит твоя оснавная задача повисла и ее надо перезапускать. Сбрасывать WatchDog можно по разному. Как тебе удобнее.
Едиственное замечание, это должна быть какая-нить уникальная последовательность, которую случайно получить сложно.
Записан

Megabyte be with you!
Migmile
Помогающий

ru
Offline Offline

« Ответ #4 : 05-01-2004 12:12 » 

Гром,  суть в том, что на машинах данного типа есть аппаратный watchdog , который при отсутствии сигнала от программы просто делает холодную перезагрузку. Сам понимаешь, это сопряжено с некоторыми неудобствами типа незакрытых файлов, потерянных кластеров, дополнительных потерь на scandisk, и т.д. Идея была в программном отслеживании работы программы. Поэтому следящему процессу нужен только бинарный переключатель (работает/неработает). И вопрос в том, как получить этот бит/флаг наиболее дешевым способом.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #5 : 06-01-2004 11:32 » 

Migmile, ну что сказать - самый дешевый способ сделать такое в винде, это сделать поиск адреса от второго процесса, забацать функцию опроса состояния программы, выцепить ее указатель и запускать каждый раз - ожидая результат.
Если она не отработала - то все.
Вот так примерно - ты в какой системе делаешь?
Записан

А птичку нашу прошу не обижать!!!
Migmile
Помогающий

ru
Offline Offline

« Ответ #6 : 06-01-2004 13:38 » 

Гром, если честно - ни хрена не понял  Вот такой я вот
Прога под W2K
Что значит адрес 2-го процесса?
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #7 : 06-01-2004 17:01 » 

Есть такая функция GetWindowLong & SetWindowLong.
С их помощью ты можешь получить адрес функции WindowProc в процессе окна программы чужой.


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

Если так сделать - то можно послать сообщение по которому программа основная соберет отчет о своем состоянии, а потом послать требование отдать их - и получить в своей функции в качестве параметра ссылку на данные, к которым ты уже можешь обратится и скопировать их к себе и после проанализировать...

Такой метод называют Хук или прорыв за пределы виртуальной памяти.
Записан

А птичку нашу прошу не обижать!!!
Alf
Гость
« Ответ #8 : 06-01-2004 20:27 » 

Цитата: Гром
Есть такая функция GetWindowLong & SetWindowLong.
С их помощью ты можешь получить адрес функции WindowProc в процессе окна программы чужой.


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

Если так сделать - то можно послать сообщение по которому программа основная соберет отчет о своем состоянии, а потом послать требование отдать их - и получить в своей функции в качестве параметра ссылку на данные, к которым ты уже можешь обратится и скопировать их к себе и после проанализировать...

Такой метод называют Хук или прорыв за пределы виртуальной памяти.

А стоит ли изобретать такой сложный велосипед?
Есть ведь такой опробованный годами механизм межпроцессного общения, как COM. Основная программа - сервер COM, а программа мониторинга - клиент, который обращается через Automation к серверу с требованием дать отчет о своем состоянии. Возможен вариант наоборот - основная программа-клиент регулярно отчитывается монитору-серверу, что пока жива-здорова, но с виду это решение похуже. Все-таки в Visual Studio есть неплохие заготовки и "мастера", которые упрощают создание серверов и клиентов COM, да и документирован сей процесс неплохо.
По-моему, достоинства налицо в любом случае. Если человек уже работал с COM, воплотит эту идею без затруднений. А если еще не доводилось - заодно изучит весьма полезную технологию, в жизни весьма пригодится. Как бы .NET на пятки не наступал, уверен, что COM еще не один год нам послужит.
Записан
Migmile
Помогающий

ru
Offline Offline

« Ответ #9 : 09-01-2004 10:43 » 

Гром, спасибо,совсем забыл об этой методе Отлично
Alf, COM не пройдут (т.е. не подойдут) Проект сделан на CVI 5.0 (это промышленный компайлер С от National Instruments) И в нем все по другому! (не совсем конечно, но многое Жаль ). Для начала обмен сделал через MAPing памяти (если интересно - покажу, есть странный момент).
COM копал года 3 назад, сейчас уже ничего не помню. Интересная идея, но реализован - по-мелкософтовски.
Записан
Migmile
Помогающий

ru
Offline Offline

« Ответ #10 : 13-01-2004 17:57 » 

Выкладываю СЫРОЙ код - на причесывание нет времени (и это - то делалось урывками) Отлично
Найдете ошибки - буду признателен
Что может предоставлять интерес (или ключевые слова):
CreateWaitableTimer
CreateFileMapping
OpenFileMapping
MapViewOfFile
CreateProcess
CreateRemoteThread
TerminateProcess
Источники:
MSDN
http://www.windevnet.com/documents/s=7285/wdj9907c/9907c.htm
Advanced Windows, Jeffrey Richter

Файл main.cpp

#define _WIN32_WINNT 0x0400
#include <windows.h>
//#include <winbase.h>
#include "task.h"
/*
   Логика:
   1. Создать таймер
   2. Запустить исследуемый процесс
   3. Создать общую область через Mapping
   4. Периодически по таймеру проверять Жив/Мертв исследуемый процесс
   5. If (dead)
   5.1 Внедрить в исследуемый процесс запрос на останов
   5.2 Если через н сек не завершится - TerminateProcess
   5.3 go to 2
*/

#define INTERVAL -10000000        /* 1 sec */

HANDLE hTimer;

bool inline IsEnd();
void StartTask();
void MakeConnect();

Task tsk1("test.exe");

//_______________________________________________________________________
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
 LARGE_INTEGER li;
 
 hTimer = CreateWaitableTimer(NULL,FALSE,NULL);
 if (!hTimer)
 {
  throw "can't create timer";
 }
 li.QuadPart=INTERVAL;

 
 if (!tsk1.Start()) throw "can't start";
 tsk1.WaitForProcess(1000);
 MakeConnect();
// MemSharePtr=tsk1.MakeShare(10);

 do
 {
  if (!SetWaitableTimer(hTimer,&li,0,NULL,NULL,0))
  {
   throw "can't set timer";
  }
  WaitForSingleObject(hTimer,INFINITE);
//  MessageBox(0,"!","",0);
 } while(!IsEnd());

 if (!tsk1.WaitForProcess(1000))
 {
  int res;
  res=tsk1.End(FALSE);
 }

 tsk1.CloseHandle();
 CloseHandle(hTimer);
 return 0;
}
//---------------------------------------------------------------------------

static void * MemSharePtr;
unsigned int MyCounter;
void MakeConnect()
{   // Создадим общую область и прочтем начальные значения счетчика
   
    MemSharePtr=tsk1.MakeShare(10);
    if (MemSharePtr!=NULL)
    {
      MyCounter=*((unsigned int*)MemSharePtr);
    }
    else MyCounter=-1;
}


bool IsEnd()
{
   // Проверка процесса - жив - мертв?
   // Через общую память проверяем счетчик, периодически записываемый туда
   // // счетчик обновляется 1 раз в сек, сл. отл
   unsigned int cnt;
   int l;
   if (MyCounter!=-1)
   {
      MyCounter++;
      cnt=*((unsigned int*)MemSharePtr);
      if (MyCounter<cnt)MyCounter=cnt;
      l=MyCounter-cnt;
       if (MyCounter-cnt>5)
      {
         return true;   // разница в 5 единиц  срабатывания таймера
      }
   }
   return false;
}

Файл task.cpp

#include <windows.h>
#include "task.h"

void * GetFileMapping(char *FName,char *MapName,int size,bool New);
void CloseMapping(void * fldat);

Task::Task()
{
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
}

Task::Task(const string fName):FName(fName)
{
    ZeroMemory( &si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
}

int Task::Start()
{    // Step 1: Start the main programm
    return CreateProcess( NULL,const_cast<char *>(FName.c_str()),
                     NULL,NULL,FALSE,0,NULL,NULL,&si,&pi );
}

int Task::WaitForProcess()
{    // Wait until process exits.
 return (WaitForSingleObject( pi.hProcess,INFINITE)==WAIT_OBJECT_0)?1:0;
}

int Task::WaitForProcess(unsigned int time)
{    // Wait until process exits.
   int res;
   res=WaitForSingleObject( pi.hProcess,time);
   return (res==WAIT_OBJECT_0)?1:0;
// return (WaitForSingleObject( pi.hProcess,time)==WAIT_OBJECT_0)?1:0;
}

int Task::End(bool NoWait)
{
 DWORD thrID;
 HANDLE ht;
// Kill it Now!
 if (NoWait)  return TerminateProcess(pi.hProcess,-99);
// Let himself to close
 LPTHREAD_START_ROUTINE MR;   // get adress of ExitProcess
 HMODULE hUSRdll=LoadLibrary("Kernel32.dll");
 MR=(LPTHREAD_START_ROUTINE)GetProcAddress(hUSRdll,"ExitProcess1");
 if (MR==NULL) return TerminateProcess(pi.hProcess,-99);
 ht=CreateRemoteThread(pi.hProcess,NULL,0,MR,NULL,0,&thrID);
 ::CloseHandle(ht);
// wait for successful finishing
 if (ht!=NULL || !WaitForProcess(500)) return TerminateProcess(pi.hProcess,-99);
 return 1;   // All are ok Не понялНе понял?
}

void Task::CloseHandle()
{
 // Close process and thread handles.
 ::CloseHandle( pi.hProcess );
 ::CloseHandle( pi.hThread );
}

void * Task::MakeShare(int size)
{
 // Получить указатель на расSharенную память
  MemSharePtr=(char *)GetFileMapping(NULL,"MIG_SH_MEM",size,false);
  return MemSharePtr;
}

void Task::CloseShare()
{
 CloseMapping(MemSharePtr);
}

Файл Share.cpp

#include <windows.h>
#include <stdio.h>
#pragma hdrstop

//---------------------------------------------------------------------------

void * GetFileMapping(char *FName,char *MapName,int size,bool New);
void CloseMapping(void * fldat);

void * GetFileMapping(char *FName,char *MapName,int size,bool New)
{
 HANDLE hfile=INVALID_HANDLE_VALUE;
 if (FName!=NULL)
 {
  hfile=CreateFile(FName,GENERIC_READ|GENERIC_WRITE,
                        FILE_SHARE_READ| FILE_SHARE_WRITE, NULL, OPEN_EXISTING,//CREATE_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL,NULL);

  if (hfile==INVALID_HANDLE_VALUE)
  {
   throw "Error create file";
   return NULL;
  }
 }
 HANDLE hfmap;
 if (New) hfmap=CreateFileMapping(/*(HANDLE)0xFFFFFFFF*/hfile,NULL,
                                    PAGE_READWRITE,0,size,MapName);
 else hfmap=OpenFileMapping(FILE_MAP_READ|FILE_MAP_WRITE,FALSE,MapName);
 if (hfmap==NULL)
 {
  throw "Error create File Mapping";
  return NULL;
 }
 if (hfile!=INVALID_HANDLE_VALUE) CloseHandle(hfile);
 char * fldat=(char*)MapViewOfFile(hfmap,FILE_MAP_WRITE,0,0,0);
// CloseHandle(hfmap);  !!!! нельзя закрывать этот handle!!!!
 if (fldat==NULL) throw "error map";
 return (void *)fldat;
}


void CloseMapping(void * fldat)
{
 UnmapViewOfFile(fldat);
}
//---------------------------------------------------------------------------
Записан
Deke
Гость
« Ответ #11 : 13-01-2004 19:08 » 

Цитата: Migmile
Имеется важная задача task1.exe, выолняющаяся непрерывно. В случае ее неверной работы необходимо ее перезапустить.


Если под неверной работой подразумевается именно зависание, и если task1 создает хотя бы одно окно, то всю работу можно переложить на Windows. Там есть недокументированные функции, которые позволяют определить, зависло приложение или нет. Если интересно - выложу больше инфы.
Записан
Migmile
Помогающий

ru
Offline Offline

« Ответ #12 : 14-01-2004 10:01 » 

Цитата

Там есть недокументированные функции, которые позволяют определить, зависло приложение или нет. Если интересно - выложу больше инфы.

Очень интересно!
Записан
Deke
Гость
« Ответ #13 : 14-01-2004 14:25 » 

Ok, вот инфа, вытянутая мной с какого-то сайта:

How the Windows Task Manager determines when the application is not responding?
A couple of weeks ago I've been writing some functions for Remote Task Manager and when I've compared RTM with the Windows NT Task Manager I saw that the standard task manager displays the status of the applications (running or not responding). I've thought the standard task manager sends (through the SendMessageTimeout function) a message to the main application window and if the function fails or time out – the application has the status not responding otherwise running status. But in a few minutes I found a much better solution.
The trick here is that we need to call an undocumented function from the User32.dll. This function presents in the Windows 95/98 as well as in the Windows NT/2000 but with different names, IsHungAppWindow in NT systems and IsHungThread in 9x systems. I'll try to describe the prototypes for them:
BOOL IsHungAppWindow (
HWND hWnd, // handle to main app's window
);
and:
BOOL IsHungThread (
DWORD dwThreadId, // The thread's identifier of the main app's window
);
Unfortunately, Microsoft doesn't provide us with the exports symbols in the User32.lib for these functions, so we should load them dynamically using the GetProcAddress and GetModuleHan-dle functions:
typedef BOOL (WINAPI *PROCISHUNGAPPWINDOW) (HWND);
typedef BOOL (WINAPI *PROCISHUNGTHREAD) (DWORD);

PROCISHUNGAPPWINDOW IsHungAppWindow;
PROCISHUNGTHREAD IsHungThread;

HMODULE hUser32 = GetModuleHandle("user32");
IsHungAppWindow =(PROCISHUNGAPPWINDOW)GetProcAddress(hUser32,
   "IsHungAppWindow");
IsHungThread =(PROCISHUNGTHREAD)GetProcAddress(hUser32,"IsHungThread");
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines