WedX - журнал о программировании и компьютерных науках

Сон демона C()

Я запускаю простой тест демона на С++. Он отлично работает без sleep(), но если я добавлю функцию sleep(), он запускается один раз, а затем остается в спящем режиме. Кроме того, первый запуск должен напечатать один раз "Hello" в файле logs/log.dat, но этого тоже не происходит. Вот код:

 #include <cstdlib>  
 #include <cstdio>  
 #include <iostream>  
 #include <unistd.h>  
 using namespace std;  
 int main(int argc, char** argv) {  
    FILE *f = NULL;   
    if ((f = fopen("logs/log.dat  ", "w")) != NULL) {  
        if (daemon(0, 0) >= 0) {  
            while (true) {  
                fprintf(f, "%s\n", "Hello");  
                sleep(5);  
            }  
        } else {  
            fprintf(f, "%s\n", "Error detaching terminal");  
        }  
    } else {  
        printf("%s\n", "Cannot open log file");  
    }  
    return 0;  
}
31.08.2010

  • Чтобы отформатировать код на SO, выберите его и нажмите кнопку 101010. 01.09.2010
  • Будьте осторожны с пробелами в имени файла. Некоторые файловые системы имеют большое значение. 01.09.2010
  • @Martin: если это не C++, то какой это язык? Чтобы заставить 'using namespace std;' работать как код C, требуется некоторый трюк с макросами, и имена заголовков также неортодоксальны для C, но это все обычно для C++. Конечно, код можно было бы написать на C, если бы материал до main() был очищен. 01.09.2010
  • @Jonathan: Это действительно что-то делает. Это требуется только потому, что OP использует версии файлов заголовков C++. В вышеперечисленном нет части, относящейся к C++, это исключительно C. И, пометив проблему как C, мы получаем целую группу людей, которые намного лучше используют вышеуказанную функциональность, чем пользователи C++ (которые не будут так хорошо знакомы с выше в качестве экспертов C). 01.09.2010

Ответы:


1

Попробуйте добавить fflush() после fprintf(). Возможно, он работает, но просто еще не записал данные на диск.

31.08.2010
  • Также хорошим тоном является закрытие файла перед завершением программы. 01.09.2010
  • @Greg: программа не завершается. 01.09.2010

  • 2

    Что находится в функции daemon()? В частности, закрывает ли он открытые файлы, кроме стандартного ввода, стандартного вывода и стандартной ошибки? Если это так, то последующие операторы fprintf() завершатся ошибкой, потому что файл, который был открыт до того, как вы вызвали daemon(), впоследствии закрывается.

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

    Самый быстрый способ проверить эту гипотезу — открыть файл журнала после демонизации.

    Обратите внимание, что некоторые подпрограммы daemon() также меняют каталог - обычно в корневой каталог. Это вызовет у вас головную боль с относительным путем к файлу журнала.


    В MacOS X функция daemon(3) предоставляется с объявлением в <stdlib.h>; он был представлен в BSD 4.4, кажется:

    СИНТАКСИС

    #include <stdlib.h>
    
     int
     daemon(int nochdir, int noclose);
    

    ОПИСАНИЕ

    Функция daemon() предназначена для программ, желающих отсоединиться от управляющего терминала и работать в фоновом режиме как системные демоны. [...]

    Если аргумент nochdir не равен нулю, daemon() изменяет текущий рабочий каталог на корень (/).

    Если аргумент noclose не равен нулю, daemon() будет перенаправлять стандартный ввод, стандартный вывод и стандартную ошибку в /dev/null.


    Вы можете проверить Исходный код FreeBSD 8.

    Поскольку вызов daemon() дважды передает 0, код делает chdir("/") и повторно подключает файловые дескрипторы 0, 1, 2 к '/dev/null'. Страница руководства продолжает обсуждение fork(2) и setsid(2). Таким образом, мы можем быть умеренно уверены в том, что стандартные каналы ввода-вывода вашей программы переподключены к /dev/null, а текущий каталог изменен на корневой.

    На справочной странице упоминается, что вы должны быть осторожны, чтобы все открытые файлы имели файловый дескриптор больше 2, чтобы избежать проблем. Можете ли вы где-нибудь напечатать 'fileno(f)' - это целое число - и убедиться, что оно больше 2. Если оно недостаточно велико, то это и есть причина вашей проблемы; не запускайте свою программу, если какой-либо из stdin, stdout или stderr уже закрыт.

    Это еще не объясняет ни отсутствие данных в файле, ни то, почему sleep() влияет на результат. Конечно, классическая реализация sleep() возится с сигналами и SIGALRM; справочная страница для daemon(3) упоминает SIGHUP. Однако реализация sleep(3) во FreeBSD 8 использует системный вызов nanosleep(2).

    Итак, я собираюсь согласиться с предложением Джея — файл будет полностью буферизован, и вам придется ждать большого количества 5-секундных циклов, чтобы напечатать достаточно данных для очистки буфера (для этого может потребоваться 4096 байтов при 6 байтах). за 5 секунд, потребуется около часа, чтобы создать что-либо в файле). Добавление fflush(), скорее всего, решит проблему «неотображения сообщения». В качестве альтернативы используйте setvbuf(f, 0, _IONBF, 0);, чтобы отключить всю буферизацию, или setvbuf(f, 0, _IOLBF, BUFSIZ);, чтобы включить буферизацию строк. И sleep() является фактором просто потому, что он сильно замедляет обработку.

    01.09.2010

    3

    У меня была аналогичная проблема, но поскольку я использовал системный журнал, использование fflush() было невозможно. В моем случае решением было изменить отладочное сообщение.

    Из:

    syslog(LOG_DEBUG, "DEBUG: tick");
    

    To:

    syslog(LOG_DEBUG, "DEBUG: tick %d", i); // i is increased in the loop
    

    Так что каждый раз было разное сообщение.

    26.12.2014
    Новые материалы

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

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]