Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> "Сигнал" из среды в приложение 
V
    Опции темы
cupper
Дата 28.2.2012, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Есть кросс платформенное консольное приложение. Нужно научить его реагировать на событие из вне. Одно единственное.

В линуксе можно заюзать сигналы и например SIGUSR1. понятие не имею как это сделать в винде. Это событие нужно уметь посылать из командной строки.

PS. Про SIGUSR1 пишут что то не совсем понятное в случае много поточности, что мол его нельзя использовать если приложение многопоточное. Но я как то не увидел почему и чем заменить...
PM MAIL   Вверх
tzirechnoy
Дата 28.2.2012, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



В юниксах для таких вещей сейчас есть сокеты.

В виндах тожэ, в общем, есть -- но только ipv4 с вытекающим ограничением на пространство имён.

Да, а SIGUSR в многопоточных приложэниях использовать вполне реально. Уж не сложнее, чем писать правильное многопоточное приложэние.

PM MAIL   Вверх
boostcoder
Дата 28.2.2012, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



cupper, юзай локальные сокеты или IPC.

PM WWW   Вверх
feodorv
Дата 29.2.2012, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(cupper @  28.2.2012,  16:58 Найти цитируемый пост)
понятие не имею как это сделать в винде

В принципе, помимо сокетов и пр. возможны ещё варианты:
1/ в консольном приложении создать именованное событие и висеть на нём, а в специальном приложении (запускаемом из командной строки) делать SetEvent
2/ в консольном приложении можно поставить обработчик особых событий SetConsoleCtrlHandler, а потом просто жать ^C или ^Break, а в обработчике коректно отлавливать это событие; при необходимости можно в консольный процесс послать ^C или ^Break программно.

Это сообщение отредактировал(а) feodorv - 29.2.2012, 15:34


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
cupper
Дата 1.3.2012, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Что то я не как не осмыслю локальные сокеты. Нигде не могу найти описание что это и как это. Так же в бусте не могу понять где они... подскажите ?

Добавлено @ 10:12
Цитата(feodorv @ 29.2.2012,  15:32)
Цитата(cupper @  28.2.2012,  16:58 Найти цитируемый пост)
понятие не имею как это сделать в винде

В принципе, помимо сокетов и пр. возможны ещё варианты:
1/ в консольном приложении создать именованное событие и висеть на нём, а в специальном приложении (запускаемом из командной строки) делать SetEvent
2/ в консольном приложении можно поставить обработчик особых событий SetConsoleCtrlHandler, а потом просто жать ^C или ^Break, а в обработчике коректно отлавливать это событие; при необходимости можно в консольный процесс послать ^C или ^Break программно.

^C и так ловится что бы корректно завершать работу. Не стоит использовать вещи не по назначению.
Нужно обойти без написани доп. апликухи для того что бы послать "сигнал".

Цитата

Да, а SIGUSR в многопоточных приложэниях использовать вполне реально. Уж не сложнее, чем писать правильное многопоточное приложэние.

Вполне реально ? А при каких случаях не реально ?
Что такое правильное много поточное приложения ?
Что такое неправильное ?

Это сообщение отредактировал(а) cupper - 1.3.2012, 10:15
PM MAIL   Вверх
EnergoHokum
Дата 1.3.2012, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 600
Регистрация: 10.11.2006
Где: Россия, Ставропол ь

Репутация: нет
Всего: 6



А кто будет отдавать этот сигнал (реализацию пока не обсуждаем)? Приложение, находящееся на это-же компьютере? Аппаратный какой-нить сигнал? Приложение, но по сети?
PM MAIL ICQ   Вверх
xvr
Дата 1.3.2012, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Попробуйте задействовать fifo (через mkfifo) на Linux, и named pipe на Windows. Код реализации в приложении конечно будет разный (его можно засунуть под #ifdef), а с командной строки будет выглядить приблизительно одинаково:
Код

Linux:
echo 1 > /your/fifo/name

Windows:
echo 1 > \\.\pipe\your_pipe_name


PS. Вот тест для WIndows -
Код

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

int main()
{
 PSECURITY_DESCRIPTOR pSD=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
 if (!pSD) return 1;
 if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) return 1;
 if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE)) return 1;
 SECURITY_ATTRIBUTES sa;
 memset(&sa,0,sizeof(sa));
 sa.nLength=sizeof(sa);
 sa.lpSecurityDescriptor=pSD;
 
 HANDLE srv_obj_handle=CreateNamedPipe("\\\\.\\pipe\\a",PIPE_ACCESS_INBOUND,PIPE_TYPE_BYTE|PIPE_WAIT,10,
  1000,1000,1000,&sa);
 LocalFree(pSD);
 if (srv_obj_handle==INVALID_HANDLE_VALUE)
  {
   return 1;
  }
 if (!ConnectNamedPipe(srv_obj_handle,NULL) && GetLastError()!=ERROR_PIPE_CONNECTED)
  {
   return 1;
  }

 char b[128];
 DWORD cnt=0;
 ReadFile(srv_obj_handle,b,128,&cnt,NULL);
 b[cnt]=0;
 printf("%s\n",b);
 return 0;
}

PM MAIL   Вверх
cupper
Дата 1.3.2012, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(xvr @ 1.3.2012,  12:42)
Попробуйте задействовать fifo (через mkfifo) на Linux, и named pipe на Windows. Код реализации в приложении конечно будет разный (его можно засунуть под #ifdef), а с командной строки будет выглядить приблизительно одинаково:
Код

Linux:
echo 1 > /your/fifo/name

Windows:
echo 1 > \\.\pipe\your_pipe_name


PS. Вот тест для WIndows -

Спасибо за пример с pipe, думаю можно/нужно переварить.

Я правильно понимаю что это блокирующая операция
ReadFile(srv_obj_handle,b,128,&cnt,NULL);

и что она сработает когда мы файл что то запишем ?
echo 1 > \\.\pipe\your_pipe_name

А если мне корректно нужно прервать эту операцию мне нужно просто закрыть pipe через хендлер ?

Цитата

А кто будет отдавать этот сигнал (реализацию пока не обсуждаем)? Приложение, находящееся на это-же компьютере? Аппаратный какой-нить сигнал? Приложение, но по сети?

человек с из командной строки.
PM MAIL   Вверх
xvr
Дата 1.3.2012, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(cupper @  1.3.2012,  15:16 Найти цитируемый пост)
Я правильно понимаю что это блокирующая операция

Да

Цитата(cupper @  1.3.2012,  15:16 Найти цитируемый пост)
и что она сработает когда мы файл что то запишем ?

Да


Цитата(cupper @  1.3.2012,  15:16 Найти цитируемый пост)
А если мне корректно нужно прервать эту операцию мне нужно просто закрыть pipe через хендлер ?

Наверное (не проверял, но вроде ReadFile должен отвалить с ошибкой)

PM MAIL   Вверх
bems
Дата 2.3.2012, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: нет
Всего: 88



если интересует только наступление события, без дополнительной информации, то целый пайп не нужен, хватит... м... события 
CreateEvent/OpenEvent спасет гиганта мысли


--------------------
Обижено школьников: 8
PM MAIL   Вверх
feodorv
Дата 2.3.2012, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(bems @  2.3.2012,  14:50 Найти цитируемый пост)
если интересует только наступление события, без дополнительной информации, то целый пайп не нужен, хватит... м... события 
CreateEvent/OpenEvent спасет гиганта мысли

Ха, такое решение почему-то не устраивает:
Цитата(cupper @  1.3.2012,  10:10 Найти цитируемый пост)
Нужно обойти без написани доп. апликухи для того что бы послать "сигнал".




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
bems
Дата 2.3.2012, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: нет
Всего: 88



Цитата(feodorv @  2.3.2012,  16:50 Найти цитируемый пост)
Ха, такое решение почему-то не устраивает:

для меня новость что можно сдлелать echo в пайп по имени пайпа в nt-пространстве. Я считал что нужно как минимум сделать пайпу CreateDosDevice

Ну у него же консольное приложение, моржет сделать параметр командной строки по которому прога будет устанавливать эвент и сразу выходить.

Добавлено через 7 минут и 17 секунд
Цитата(bems @  2.3.2012,  18:00 Найти цитируемый пост)
по имени пайпа в nt-пространстве

простите, стормозил, оно уже примонтировано куда следует


--------------------
Обижено школьников: 8
PM MAIL   Вверх
cupper
Дата 6.3.2012, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(xvr @ 1.3.2012,  12:42)
Попробуйте задействовать fifo (через mkfifo) на Linux, и named pipe на Windows. 
Код


 PSECURITY_DESCRIPTOR pSD=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
 if (!pSD) return 1;
 if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) return 1;
 if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE)) return 1;
 SECURITY_ATTRIBUTES sa;
 memset(&sa,0,sizeof(sa));
 sa.nLength=sizeof(sa);
 sa.lpSecurityDescriptor=pSD;

А можете подсказать зачем тут явно создается SECURITY_ATTRIBUTES ? Пытался понять чего такого особенного задается в ней но так и не понял. Много где встречал что ее обычно NULL'ом заменяют. Чем дефолтные права не подходят ?
PM MAIL   Вверх
xvr
Дата 6.3.2012, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(cupper @  6.3.2012,  13:12 Найти цитируемый пост)
А можете подсказать зачем тут явно создается SECURITY_ATTRIBUTES ?

Если его не задать, то берется значение по умолчанию:

Цитата

If lpSecurityAttributes is NULL, the named pipe gets a default security descriptor and the handle cannot be inherited. The ACLs in the default security descriptor for a named pipe grant full control to the LocalSystem account, administrators, and the creator owner. They also grant read access to members of the Everyone group and the anonymous account.
Т.е. писать в него смогут только LocalSystem account, administrators, and the creator owner. Что бы был доступ для всех и создается ACL с разрешением для всех (это в строке 4). Этот ACL и подается в lpSecurityAttributes 


Это сообщение отредактировал(а) xvr - 6.3.2012, 13:18
PM MAIL   Вверх
cupper
Дата 6.3.2012, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



что то оно работает не так как ожидалось

Блокирующей явлется операция ConnectNamedPipe и на ней зависаем до тех пор пока в пайп из консоли не запишем что нить. 
А вот операция ReadFile если есть данные читает их, если нет, позвращает управление, т.е. как будто мы установили флаг PIPE_NOWAIT
PM MAIL   Вверх
xvr
Дата 6.3.2012, 18:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(cupper @  6.3.2012,  16:04 Найти цитируемый пост)
Блокирующей явлется операция ConnectNamedPipe и на ней зависаем до тех пор пока в пайп из консоли не запишем что нить. 

Для определения факта посылки данных это в принципе тоже должно подойти

PM MAIL   Вверх
cupper
Дата 6.3.2012, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Цитата(xvr @ 6.3.2012,  18:56)
Цитата(cupper @  6.3.2012,  16:04 Найти цитируемый пост)
Блокирующей явлется операция ConnectNamedPipe и на ней зависаем до тех пор пока в пайп из консоли не запишем что нить. 

Для определения факта посылки данных это в принципе тоже должно подойти

да но это взывает другие проблемы.

Условие изменилось и теперь нужно иметь возможность обработать "сигнал", и опять начать слушать его. Для этого единственно что пришло в голову закрывать pipe (CloseHandle), и создавать заново. Потом обнаружилась функции - DisconnectNamedPipe. Но не та не другая не могут прервать ожидание ConnectNamedPipe, а это уже странно. И пока что то у меня эти pipe вызывают только огорчение.

Это сообщение отредактировал(а) cupper - 6.3.2012, 22:11
PM MAIL   Вверх
cupper
Дата 6.3.2012, 20:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 525
Регистрация: 29.11.2006

Репутация: 1
Всего: 1



Чет не как немогу врубиться в OVERLAPPED.
Таки осилил smile Надеюсь больше без подводных камней
Код

#include <iostream>
#include <string>
#include <Windows.h>

using namespace std;

HANDLE handle_ = NULL;
HANDLE stop_event = NULL;

DWORD WINAPI WorkerThreadProc( LPVOID _parameter )
{
    PSECURITY_DESCRIPTOR pSD=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
    if (!pSD) 
        return 1;
    if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
        return 1;
    if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE))
        return 1;
    SECURITY_ATTRIBUTES sa;
    memset(&sa,0,sizeof(sa));
    sa.nLength=sizeof(sa);
    sa.lpSecurityDescriptor=pSD;
    handle_ = CreateNamedPipe(L"\\\\.\\pipe\\test", PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE|PIPE_WAIT, 10, 1000, 1000, 1000, &sa);
    LocalFree(pSD);
    if (handle_==INVALID_HANDLE_VALUE)
        return 1;

    OVERLAPPED  ovl;
    HANDLE      h, handleArray[2];
    BOOL        bStop = FALSE;
    memset(&ovl, 0, sizeof(ovl));
    handleArray[0] = stop_event = CreateEvent(NULL, FALSE, FALSE, NULL);
    handleArray[1] = ovl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    while(true)
    {
        if (!ConnectNamedPipe(handle_, &ovl) && GetLastError() != ERROR_IO_PENDING) // here is blocking
        {
            CloseHandle(handle_);
            return 1;
        }
        switch(WaitForMultipleObjects(2, handleArray, FALSE, INFINITE))
        {
        case WAIT_OBJECT_0: // exit()
            {
                if(!CloseHandle(handle_))
                    return 1;
                else
                    return 0;
            }
        case WAIT_OBJECT_0 + 1: // message()
            {
                char buf[128];
                DWORD cnt=0;
                ReadFile(handle_, buf, 128, &cnt, NULL);
                buf[cnt]=0;
                cout << std::string(buf, cnt);

                if(!DisconnectNamedPipe(handle_))
                    return 1;
            }
        }
    }
    return 1;
}

void stop()
{
    SetEvent(stop_event);
}


int main()
{
    DWORD idWorkerThread = 0;
    HANDLE hWorkerThread = ::CreateThread( NULL, 0, &WorkerThreadProc, NULL, 0, &idWorkerThread );

    char a;
    cin >> a;

    stop();

    cin >> a;
} 


Это сообщение отредактировал(а) cupper - 6.3.2012, 23:01
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0722 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.