[解決済み] Linuxでデーモンを作成する
質問
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]。最初のデーモンが終了しました。
注意事項です。
実際には、シグナルハンドラを実装し、ロギングを適切に設定する必要があります(ファイル、ログレベル...)。
さらに読む。
関連
-
C 構造体定義エラー: '['トークンの前に一次式があることが予想される
-
[解決済み] MIPSのネストされたForループと配列の使用
-
[解決済み] Linuxで特定のテキストを含むすべてのファイルを検索するにはどうすればよいですか?
-
[解決済み] Linux上で動作するC++コードのプロファイリングを行うにはどうすればよいですか?
-
[解決済み] LinuxのシェルスクリプトでYes/No/Cancelの入力を促すにはどうしたらいいですか?
-
[解決済み] Linux で grep を使ってファイル名だけを表示するにはどうしたらいいですか?
-
[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
-
[解決済み] Linuxのディレクトリ内のファイルを再帰的にカウントする
-
[解決済み] C言語でランダムなint型を生成するには?
-
[解決済み】fork()、vfork()、exec()、clone()の違いについて)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
error: '.' トークンの前にunqualified-idを指定する必要があります。
-
g++が内部・外部コマンドソリューションとして認識されない、MinGWを初めて使うときの落とし穴
-
[解決済み] Code::Blocks アプリケーションをコンパイルできない
-
[解決済み] c または c++ 用のシンプルな 2 次元クロスプラットフォームグラフィックスライブラリ?[クローズド]
-
[解決済み] char *とchar[]の違い [重複]
-
[解決済み] Linuxカーネルにおけるcontainer_ofマクロの理解
-
[解決済み] C言語のコードで「:-!」とは何ですか?
-
[解決済み] POSIX」の意味を教えてください。
-
[解決済み] char s[]とchar *sの違いは何ですか?
-
[解決済み] C言語で "unsigned long "をprintfする方法は?