nixp.ru v3.0

22 января 2017,
воскресенье,
11:06:50 MSK

DevOps с компанией «Флант»
Force_Majeure написал 3 сентября 2005 года в 09:20 (236 просмотров) Ведет себя как мужчина; открыл 2 темы в форуме, оставил 10 комментариев на сайте.

Наисал простейшего демона раздвоив процесс через fork() и setsid(), родительский процесс завершился, в потомке — бесконечный цикл while. Подскажите, как теперь сделать передачу команд демону из конандной строки? Например, как системным демонам пишешь, service iptables stop и iptables завершается. Как сделать, чтобы мой демон тоже мог воспринимать команды?

Genie

команда service iptables stop на самом деле вызывает /etc/init.d/iptables, в котором и реализовано данное управления. :))

правда, не всегда это удобно именно таким образом, но кто его знает.

вообще же, сильно рекомендуется к прочтению «Inter-process communication» («Взаимодействие процессов») (у меня, правда, на примете нет таких описаний, но кто-нибудь ссылку да подкинет)

Force_Majeure

Так не обязательно именно таким способом, я же его в качестве примера привел. Но как-то управлять демоном нужно же. Как передать демону хотя бы простейшую команду завершить работу?

Genie

ловить в демоне сигнал SIGQUIT — стандартный сигнал завершения работы.

принято так же обрабатывать SIGINT — перечитать конфигурацию.

вообще же, как я уже и сказал, тебе нужно поискать и почитать про IPC механизмы.

к примеру, на том же <font color=«blue»>Opennet.ru</font>

Force_Majeure

Т.е. получается, что «общаться» с демоном можнотолько посредством отправки ему сигналов?

Force_Majeure

Вот еще такой вопрос появился. Я пишу на С++. При использовании ф-ции fork(), как я понимаю, создается вторая копия данных для новой нити процесса. Если я до вызова fork() создал динамический объект MyClass* MyCls = new MyClass(); я по логике должен вызвать деструктор для него delete MyClas; два раза, для нити-предка и для нити-потомка. А как быть если я создавал динамические объекты раньше, во время вызова fork() это неизвесно и налицо будет огромная утечка памяти. Как тут быть?

rgo

можно сделать exec.

Genie
Т.е. получается, что «общаться» с демоном можнотолько посредством отправки ему сигналов?

а прочитать предложенное было не судьба?

лениво?

или что???

способов — несколько. И ВСЕ ОНИ ОПИСАНЫ. и называются общим словом «Взаимодействие процессов», IPC.

ЧТО ТУТ НЕПОНЯТНОГО???!

Force_Majeure
Genie
а прочитать предложенное было не судьба?

лениво?

или что???

способов — несколько. И ВСЕ ОНИ ОПИСАНЫ. и называются общим словом «Взаимодействие процессов», IPC.

ЧТО ТУТ НЕПОНЯТНОГО???!

Я прочитал и про каналы и про сигналы и про очереди сообщений и про совместное пользование памятью и про управление через сокеты. Это все теория. А на форумах обычно подсказывают то, что реально используют в программах. Ты сам, например, какой способ используешь?

rgo

а как ты думаешь зачем так много способов IPC? наверное, потому, что универсального способа не существует. Ну посоветую я тебе псеводтерминал использовать — поможет? Или может pipe тебе будет удобнее? Здесь же нету телепатов, и никто не знает чем твой демон занимается и какие команды надо ему передавать.

Uncle Theodore

Это не теория, это самая что ни на есть практика. :-)

Каждый способ хорош для какой-то конкретной задачи, для нее он и используется.

Тебе надо точно определить структуру своей программы, ты увидишь, какой способ тебе лучше всего применить.

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

Если нужно только передать форканутому процессу одну-две команды (stop/restart), тогда родитель может выйти, но pid нового процесса надо сохранить в файле. Тогда твой командный интерфейс вызовется, прочитает pid из этого файла и пошлет нужный сигнал демону.

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

Я давал такие упражнения своим студентам — сделать чатовый сервер и чатовый клиент для клмандной строки и устроить между ними общение. Главное тут — строгая структуризация алгоритма. Как только ты точно знаешь, чтО тебе надо, ты увидишь, кАк это сделать.

А по поводу объектов, которые создаются до форка, да, они копируются потомком, и там их надо тоже уничтожать. Отслеживай. Только аккуратно.

pointer = new myclass()

в ребенке будет указывать в пустоту… Подумай, почему. :-)

Good Luck,

UT

Force_Majeure

Мне нужен типовой вариант демона.

Если нужно только передать форканутому процессу одну-две команды (stop/restart), тогда родитель может выйти, но pid нового процесса надо сохранить в файле. Тогда твой командный интерфейс вызовется, прочитает pid из этого файла и пошлет нужный сигнал демону

Ближе всего к этому варианту. Командный интерфейс — что имеется ввиду? Скрипт в /etc/init.d/с командами?

pointer = new myclass()

в ребенке будет указывать в пустоту… Подумай, почему. :-)

Не понял, с какой стати? Если память основного процесса копируется, указатели должны переопределиться на новый участок памяти и pointer впотомке будет указывать на другой экземпляр класса MyClass. Если я не прав, поясни, пля.

Longobard

Купи книжу Стивенса «UNIX: взаимодействие процессов» и «Разработка сетевых приложений в UNIX».

Там это все описано замечательно, с примерами и пояснениями.

Uncle Theodore

Что такое «пля»? Уж больно на «бля» похоже…

Я извиняюсь, что из меня иногда в самый неподходящий момент вылезает препод, но должен заметить, что ты взялся за дело несколько не с того конца.

Напиши парочку простеньких программулек с fork()’ом — поиграйся, посмотри, как он работает. Если чего-то не поймешь, и в книгах про это нет, спроси здесь, твоя программулька будет конкретнвм примером. То же — с разными способами передачи данных.

Извини, но твои оторванные от контекста теоретические рассуждения подвигают народ только на очередной RTFM. Ну а что еще можно сказать?

Не надо пытаться проглотить большой проект одним куском, особенно если ты не понимаешь большого количества деталей.

Good Luck,

UT

Force_Majeure

2 LONGOBARD

Вторая книжка у меня есть, ей и руководствуюсь. Того чего не понимаю — спрашиваю.

2 Uncle Theodore

Прошу прощения, «пля» — это «плz» (сокращение от пожалуйста), раскладку случайно не перекючил.

Так я и делаю, написал простейшую программу (hello word :) ) и далее подгоняю ее под свои нужды. С fork() поэкспериментировал отдельно, все правильно, указатель в потомке указывает на копию данных а не на NULL.

А вот конкретный участок кода, который вызвает затруднения:

...инициализация сокета...
int rez = fork();
switch(rez){
case0 : {
 setsid()
 signal(SIGHUP,SIG_IGN);
 rez = fork();
 switch(rez) {
  case0: {
   chdir('/')
   close(0);
   close(1);
   close(2);
   umask(0);
   while(true) {
    int conid = accept(...)
     // ВОТ ЗДЕСЬ ПРИ КАЖДОМ КОННЕКТЕ БУДЕТ ОБРАБОТКА ПОЛУЧЕНИЯ ДАННЫХ В НОВОМ ПРЦЕССЕ Т.Е. БУДУТ СКОПИРОВАНЫ ВСЕ ОБЪЕКТЫ, КОТОРЫЕ БЫЛИ СОЗДАНЫ РАНЕЕ. КАК ИХ ЧИСТИТЬ, ЕСЛИ О НИХ НИЧЕГО НЕ ИЗВЕСТНО?
    rez = fork();
    switch(rez) {
     ...
     }
    }
   }
  }
 }
}
Longobard
Force_Majeure
2 LONGOBARD

Вторая книжка у меня есть, ей и руководствуюсь. Того чего не понимаю — спрашиваю.

А тебе нужна прежде всего первая книжка :) Вопросы IPC во второй освещены весьма поверхностно

Force_Majeure

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

// Создать прослушиваемый сокет
Rez = listen(ListenId,MaxClients);
if(Rez<0) return false;
      // Создать отдельный независимый процесс и запустить в нем сокет на ожидание соединений
int NewProcess = fork();
switch(NewProcess) {
      case 0:{            // Процесс-потомок
            setsid();      // Сделать новый процесс главным в группе
            signal(SIGHUP,SIG_IGN);      // Отключаем (игнорируем) прием сигнала SIGHUP
            NewProcess = fork();      // Еще раз создаем новый процесс-потомок (чтобы процессы-зомби удалялись из таблицы процессов)
            switch(NewProcess) {
                  case 0:{            // Процесс-потомок
                        chdir("/");      // Корневой каталог - основной, чтобы избежать проблем с монтированием
                        umask(0);      // Маску режима создания файлов ставим в 0
                        close(0);      // Закрываем извеесные дескрипторы
                        close(1);
                        close(2);
                              // Ставим сокет в новом процессе на ожидание соединений
                        Listening = true;
                        while(Listeninig==true) {      // Запускаем цикл ожидания соединений от клиентов
                              sockadr_in CltSocketStruc;      // Основная структура сокета подключающегося клиента
                              int ConnectionId = accept(ListenId,(sockaddr*)&CltSocketStruc,sizeof(CltSocketStruc));
//                              cout << "[OK] Подключился клиент от "+inet_ntoa(CltSocketStruc.sin_addr) << endl;
                              // Порождаем новый процесс для принятия данных от подключившегося клиента
                              NewProcess = fork();
                                    case 0: {      // Процесс-потомок
                                          // Получить данные
                                          GetData(ConnectionId);
                                          Listening = false;      // Чтобы корректно завершить процесс выходом из цикла прослушивания
                                          break;
                                          }
                                    case -1: {      // Ошибка порождения нового процесса
//                                          Message("[ER] Ошибка перехода в режим демона");
                                          break;
                                          }
                                    default: {      // Родительский процесс
                                          // Ничего не делаем - возвращаемся на прослушивание следующего подключения от клиента
                                          break;
                                          }
                              close(ConnectionId);
                              }
                        break;
                        }
                  case -1:{      // Ошибка порождения нового процесса
//                        Message("[ER] Ошибка перехода в режим демона");
                        break;
                        }
                  default:{      // Первый процесс-потомок
                        // Просто завершаем
                        break;
                        }
                  }
            break;
            }
      case -1:{      // Ошибка порождения нового процесса
//            Message("[ER] Ошибка перехода в режим демона");
            break;
            }
      default:{      // Основной процесс (процесс-родитель)
            // Просто завершаем
            break;
            }
      }
close(ListenId);      // Закрываем ListenId
return true;

Подскажите, если я в функции GetData(ConnectinId) получаю скажем строку «QUIT» для завершения всей программы, каким способом мне сделать Listening=false в процессе, который крутит цикл while(Listening==true) чтобы корректно выйти из программы?

Uncle Theodore

Посмотри http://www.ecst.csuchico.edu/~beej/guide/net/html/clientserver.html#simpleserver

Там хороший пример сервера.

Good Luck,

UT

Force_Majeure

2 Uncle Theodore

В этом примере (как и во многих других, что я находил в и-нете) процесс просто рубится по exit(0). В man’е не сказано что exit(0) очищает динамически выделенную память, значит все остается неподчищенным?

Steck
Force_Majeure
Я прочитал и про каналы и про сигналы и про очереди сообщений и про совместное пользование памятью и про управление через сокеты. Это все теория. А на форумах обычно подсказывают то, что реально используют в программах. Ты сам, например, какой способ используешь?

Офигеть…Ты эт чего IPC теорией обзываешь то..

Тебе дельный совет дали.. И не какая это не теория Гыы..

ecobeingecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.