私はまさにその反対が欲しいこの問題。終了した後でも再起動されるプロセスを作成する方法を知りたいです。誰かが私に実装例を与えることができますか?
例えば、次のようにタイムスタンプを継続的に記録し、カウンタをログファイルにインクリメントする簡単なプロセスがあるとします。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define FILE_PATH "/home/lincoln/date.log"
int main() {
time_t current_time;
struct tm *time_info;
int counter = 0;
while (1) {
FILE *file = fopen(FILE_PATH, "a");
if (file == NULL){
perror("Failed to open the file");
return 1;
}
// Get the current timestamp
time(¤t_time);
time_info = localtime(¤t_time);
// Format the timestamp
char timestamp[25];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", time_info);
// Write timestamp and counter to the file
fprintf(file, "%s | Counter: %d\n", timestamp, counter++);
fflush(file);
fclose(file);
sleep(5); // Sleep for 5 seconds
}
return 0;
}
バイナリファイル(ELFファイル)を生成するには、次のコマンドを使用しました。
gcc logger_file.c -o date_test
(これは単なる例であることに注意してください。継続的に印刷する「hello world」プログラムです。継続的に実行される効果を観察したいので、ロギングを選択しました。)
~から引用された質問(私が間違っている場合は修正してください。)これは、子プロセスの親プロセスを監視してこれを行います。子プロセスが終了すると、親プロセスはそれを再開します。概念は理解していますが、実際にどのように実装されているのかわかりません。
提供されたバイナリの例を使用してこれを実装する方法を示すことができる人はいますか? (私の研究へのより多くのリンクも歓迎します。)
より多くの情報が必要な場合はお知らせください。
編集する:私の実装では、組み込みデバイスで実行する予定です。基本的に私が働く環境ではシステム初期化ブートシステムとしてビジーボックスv1.23.2armv7プロセッサで実行される3.18.44カーネルのツールセットとして使用されます(私はgcc-12-arm-linux-gnueabi-base
ツールチェーンを使用しています)。
ベストアンサー1
プロセスが終了すると、自分で復活することはできません。それは死んで、実際には何もできません(それがポイントです)。
スーパーバイザにプロセスのステータスを確認し、前のプロセスが終了したときに新しいプロセスを作成するように指示できます。
ほとんどすべて(一部のニッチや小規模コンテナ指向を除く)Linuxディストリビューションはこれを簡単にします。 systemdがこれを行うことができます。何をすべきかは、systemdサービス単位ファイルを作成して設定することだけです。Restart=
財産always
、または、on-abnormal
またはon-abort
。それだけです!
その後、systemdは監督者として機能し(procfsなどを扱うために自分の監督者を作成する必要はありません)、すべてがすぐに機能します。明らかにサービスを停止して再起動しますsystemctl
。
それでは、実際にこれを行う方法を尋ねます。procfs
これは方法の1つと言及しました。 /proc/{PID}ディレクトリまたはその中のメモリマップを見てください。
しかし、規制当局は通常彼らがすることは(そしてsystemdのservice.cもこれを行います)ハンドラを登録することですSIGCHLD
:プロセスの子プロセスが終了すると、親プロセスはシグナルを受け取ります。これは、監督者が実際に監督対象プロセスを子プロセスとして開始するためにfork
機能します。
したがって、おおよそ以下が必要です。古代のOracleガイドで緩やかに適用そしてLinuxのマニュアルページは次のとおりですman waitpid
。
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
void proc_exit() {
int wstat;
pid_t pid;
while (1) {
int retval = waitpid(pid, &wstat, WNOHANG);
if (retval == 0)
return;
else if (retval == -1)
return;
else
printf("Return code: %d\n", WEXITSTATUS(wstat));
}
}
int main() {
signal(SIGCHLD, proc_exit);
switch (fork()) {
case -1:
perror("main: fork");
exit(0);
case 0:
printf("I'm alive (temporarily)\n");
exit(42);
default:
pause();
}
}
子プロセスはfork
戻り0をチェックするので、これは印刷プロセスです"I'm alive…
。ここから別の実行可能ファイル(つまり管理されているプロセス)を作成するには、を呼び出しますexecve
。