1. ホーム
  2. c

[解決済み] Linuxでデーモンを作成する

2022-07-08 04:48:20

質問

Linux で、ファイルシステムの変更を監視する停止できないデーモンを追加したいと思います。 何らかの変更が検出された場合、それが起動されたコンソールへのパスと改行が書き込まれる必要があります。

私はすでにファイルシステムを変更するコードをほとんど用意していますが、デーモンを作成する方法を見つけ出すことができません。

私のコードはここからです。 http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

フォークの後はどうする?

int main (int argc, char **argv) {

  pid_t pID = fork();
  if (pID == 0)  {              // child
          // Code only executed by child process    
      sIdentifier = "Child Process: ";
    }
    else if (pID < 0) {
        cerr << "Failed to fork" << endl;
        exit(1);
       // Throw exception
    }
    else                                   // parent
    {
      // Code only executed by parent process

      sIdentifier = "Parent Process:";
    }       

    return 0;
}

どのように解決するのですか?

<ブロッククオート

Linux で、ファイルシステムの変更を監視する、停止できないデーモンを追加したい。何らかの変更が検出された場合、それが起動されたコンソールへのパスと改行を書き込む必要があります。

デーモンはバックグラウンドで動作し、(通常...) TTY に属さないため、おそらく望む方法で stdout/stderr を使用することができないのです。 通常、syslog デーモン ( syslogd ) は、ファイルへのメッセージのロギング (デバッグ、エラー、...) のために使用されます。

そのほかにも、いくつかの 必須ステップ があります。


私の記憶が正しければ、これらの手順は

  • フォーク fork が成功した場合、親プロセスの & を終了させます。-親プロセスが終了したため、子プロセスはバックグラウンドで実行されるようになりました。
  • setid - 新しいセッションを作成する。呼び出したプロセスは、新しいセッションのリーダとなり、新しいプロセスグループのリーダとなる。プロセスはこれで制御端末 (CTTY) から切り離される。
  • シグナルをキャッチする - シグナルを無視したり、処理したりします。
  • 再度フォークする & 親プロセスを終了させ、セッションをリードするプロセスを確実に取り除くようにします。(セッションリーダーだけが再びTTYを得ることができます)。
  • chdir - デーモンの作業ディレクトリを変更します。
  • umask - デーモンの必要性に応じてファイルモードマスクを変更します。
  • 閉じる - 親プロセスから継承された、開いているすべてのファイルディスクリプタを閉じます。

出発点を与えるために。基本的なステップを示すこのスケルトン コードをご覧ください。このコードは GitHub でフォークすることができます。 linux デーモンの基本的なスケルトン

/*
 * daemonize.c
 * This example daemonizes a process, writes a few log messages,
 * sleeps 20 seconds and terminates afterwards.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>

static void skeleton_daemon()
{
    pid_t pid;

    /* Fork off the parent process */
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* On success: The child process becomes session leader */
    if (setsid() < 0)
        exit(EXIT_FAILURE);

    /* Catch, ignore and handle signals */
    //TODO: Implement a working signal handler */
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);

    /* Fork off for the second time*/
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* Set new file permissions */
    umask(0);

    /* Change the working directory to the root directory */
    /* or another appropriated directory */
    chdir("/");

    /* Close all open file descriptors */
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>=0; x--)
    {
        close (x);
    }

    /* Open the log file */
    openlog ("firstdaemon", LOG_PID, LOG_DAEMON);
}

int main()
{
    skeleton_daemon();

    while (1)
    {
        //TODO: Insert daemon code here.
        syslog (LOG_NOTICE, "First daemon started.");
        sleep (20);
        break;
    }

    syslog (LOG_NOTICE, "First daemon terminated.");
    closelog();

    return EXIT_SUCCESS;
}



  • コードをコンパイルします。 gcc -o firstdaemon daemonize.c
  • デーモンを起動します。 ./firstdaemon
  • すべてが正しく動作しているかどうかを確認します。 ps -xj | grep firstdaemon

  • このような出力になるはずです。

+------+------+------+------+-----+-------+------+------+------+-----+
| ppid | pid | pgid | sid | tty | tpgid | stat | uid | time | cmd | 。
+------+------+------+------+-----+-------+------+------+------+-----+
| 1 | 3387 | 3386 | 3386 | ?   | -1 | S | 1000 | 0:00 | ./ |
+------+------+------+------+-----+-------+------+------+------+-----+

ここで見るべきものは

  • デーモンは制御するターミナルがない ( TTY = ? )
  • 親プロセスID ( PPID ) は 1 (initプロセス)
  • PID != SID ということは、私たちのプロセスはセッションリーダーではないことを意味します。

    (2番目のfork()のせいです)
  • PID != SID のため、私たちのプロセスは は再びTTYを制御することはできません。

syslogを読んでいます。

  • syslog ファイルを探します。私のはここです。 /var/log/syslog
  • を行う。 grep firstdaemon /var/log/syslog

  • このような出力になるはずです。

  firstdaemon[3387]: 最初のデーモンが起動しました。
  firstdaemon[3387]。最初のデーモンが終了しました。



注意事項です。 実際には、シグナルハンドラを実装し、ロギングを適切に設定する必要があります(ファイル、ログレベル...)。

さらに読む。