ソケットを介して通信する2つのLinuxシステム(デスクトップとARMベースの開発ボード)があります。
サーバーが特定の定義済みメッセージを送信したときに、クライアントアプリケーション(開発ボードで実行中)を再起動(またはリセット)したいと思います。 Linuxを再起動(再起動)したくありません。クライアントアプリケーションが自動的に再起動したいだけです。
どうすればいいかわからない。
これを行う通常の方法は、プログラムを終了させ、監視システムを使用して再起動することです。 init
プログラムは、このような監視システムを提供します。多くの異なるinitプログラム(SysVinit、BusyBox、Systemdなど)があり、構成メカニズムは完全に異なります(常に構成ファイルを作成しますが、ファイルの場所と構文は異なります)。使用しています。ブート時または明示的な要求時にプログラムを起動し、プログラムが停止した場合は再起動するようにinitを構成します。より洗練された監視プログラムもありますが、必要なようには聞こえません。この方法には、プログラムが単独で再起動を実行するよりも多くの利点があります。これは標準であるため、サービスの作成方法を気にすることなく、一連のサービスを再起動できます。バグのためにプログラムが死んでも動作します。
プロセスに終了するよう指示する標準的なメカニズムがあります signals 。プログラムにTERMシグナルを送信します。プログラムでクリーンアップを実行する必要がある場合は、シグナルハンドラを記述します。これは、このようなコマンドを送信する管理チャネルがある場合に、プログラム固有のコマンドをシャットダウンさせるコマンドを排除するものではありません。
特定のメッセージを受信したら、クライアントを_/proc/self/exe
_にexecさせます。実行可能ファイルが実際にファイルシステムのどこにあるかを知る必要はありません。また、main()
のargv
を再利用して、新しい引数ベクトルを作成できます。
_#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char buf[32] = {};
char *exec_argv[] = { argv[0], buf, 0 };
int count = argc > 1 ? atoi(argv[1]) : 0;
printf("Running: %s %d\n", argv[0], count);
snprintf(buf, sizeof(buf), "%d", count+1);
sleep(1);
execv("/proc/self/exe", exec_argv);
/* NOT REACHED */
return 0;
}
_
この_restart.c
_は次のように実行されます。
_$ gcc restart.c
$ ./a.out 3
Running: ./a.out 3
Running: ./a.out 4
Running: ./a.out 5
_
クライアントアプリケーションがLinuxサービスの場合は、次のコマンドで再起動できます。
service <clientapp> restart
またはその構成を強制的に再読み込みします:
service <clientapp> reload
service <clientapp> force-reload
多くの場合、それがカスタムアプリケーションである場合は、信号またはイベントの受信時に自分自身を再起動するか、構成を再読み込みする機能をコードに埋め込む必要があります。そうしないと、最後の手段として、いつでもクライアントアプリを強制終了できます。
pkill -9 <clientapp>
その後、再起動しますが、アプリが未確定の状態のままになるため、醜いです。