VS2019 C ++(1.4.3)に基づくクロスプラットフォーム(Linux)開発-信号シールド

I.はじめに

前回の記事から、カーネルでシグナルを受信して​​何もしなかった場合、プロセスが中断されることがわかっています。このとき、シグナルをシールドする必要があります。

2.関数プロトタイプ

1.sigprocmask関数 

ヘッダーファイル:#include <signal.h>

機能:プロセスの信号シールドワードを読み取るか変更し、認識されない信号または不要な信号をシールドして、プロセスが正常に実行されるようにします。
プロトタイプ:int sigprocmask(int how、const sigset_t * set、sigset_t * oset);

パラメータの説明:

        osetがnull以外のポインターである場合、読み取りプロセスの現在のシグナルマスクはosetパラメーターを介して渡されます。setがnull以外のポインターの場合、プロセスのシグナルマスクが変更され、パラメーターhowは変更方法を示します。osetとsetの両方がnull以外のポインタである場合は、最初に元の信号マスクワードをosetにバックアップしてから、setとhowパラメータに従って信号マスクワードを変更します。現在のシグナルマスクワードがマスクであると仮定して、次の表は、howパラメーターのオプションの値を示しています。

戻り値:成功した場合は0、エラーの場合は-1

パラメータどのようにオプション値
SIG_BLOCK 信号ロック(シールド)
SIG_UNBLOCK 信号がロックされていない(ブロックされていない)
SIG_SETMASK 現在のシグナルマスクワードをsetが指す値に設定することは、現在のシグナルマスクワードをsetが指す値に設定することと同じです。

信号セット操作機能は以下のとおりです。

#include <signal.h>
/* Clear all signals from SET.  */
int sigemptyset(sigset_t *set);// 清空信号集
 /* Set all signals in SET.  */
int sigfillset(sigset_t *set);// 所有信号加进去 32 33 是没有的
int sigaddset(sigset_t *set, int signo);// 增加信号
int sigdelset(sigset_t *set, int signo);//删除信号集的某个信号
int sigismember(const sigset_t *set, int signo);// 信号是否在集合里面
 /* Return 1 if SIGNO is in SET, 0 if not.  */

1.基本的な手順を実装します

  • 最初に信号セットを準備します(これは、信号をシールドするためのコンテナーとして、またはブラックリストに友達を追加するためのコンテナーとして理解できます)
  • シグナルコンテナの初期化
  • マスクされた信号を追加する
  • sigprocmaskを呼び出して、設定された信号セットをマスクします

2.コード

    //准备信号容器
	sigset_t arr;
	//容器初始化
	sigemptyset(&arr);
	//添加屏蔽的信号
	sigaddset(&arr,SIGUSR1);
	sigaddset(&arr, SIGUSR2);

	if (sigprocmask(SIG_BLOCK,&arr,NULL) < 0)
	{
		perror("sigprocmask error");
		exit(0);
	}
	while (true)
	{
		cout << "当前进程运行中 ...pid =" << getpid() << endl;
		sleep(1);
	}

3.操作効果

下の図からわかるように、この時点では常にシグナルがプロセスに送信され、中断されることはありません。

4.分析

上記の例では、信号をブロックすることは、実際には女の子がボーイフレンドをブラックリストに登録するようなものですが、女の子はボーイフレンドが電話をかけてメッセージを送信したかどうかを知りたがっています(たぶん、彼女がやわらかくなった場合、彼女はから削除されます)ブラックリスト)。次に、接続があるかどうかを知りたい場合は、次のようにsigpending関数を使用する必要があります

2.sigpending関数

#include <signal.h>
int sigpending(sigset_t * set);

機能:現在のプロセスの保留中のシグナルセットを読み取ります(保留中は、シグナルがまだ応答ハンドラーにバインドされていないことを意味します。つまり、ブラックリストから削除するか、ブラックリストに永久に保持するかは決定されません。彼に会いたい最後に接続はありますか)
戻り値:成功した場合は0、エラーの場合は-1 

 例

1.コード

    //准备信号容器
	sigset_t arr;
	//容器初始化
	sigemptyset(&arr);
	//添加屏蔽的信号
	sigaddset(&arr,SIGUSR1);
	sigaddset(&arr, SIGUSR2);

	if (sigprocmask(SIG_BLOCK,&arr,NULL) < 0)
	{
		perror("sigprocmask error");
		exit(0);
	}


	while (true)
	{
		cout << "当前进程运行中 ...pid =" << getpid() << endl;
		sleep(10);
		//查看未决信号集(黑名单)
		if (sigpending(&arr) == 0)
		{
			//判断未决信号是谁发的
			cout << "黑名单中的电话打来"  << endl;
			if (sigismember(&arr,SIGUSR1))
			{
				cout << "黑名单中的SIGUSR1打来电话" << endl;
			}
			if (sigismember(&arr, SIGUSR2))
			{ 
				cout << "黑名单中的SIGUSR2打来电话" << endl;
			}
		}
	}
	

	return 0;

知らせ:

①if(sigpending(&arr)== 0)は、関数が正常に実行できるかどうかを判断するだけであり、信号が信号セットに正常に挿入されたかどうかは判断しません。

②保留中の信号セット(未処理の信号)をsigemptysetで空にすることはできないようです(今後の調査のため)

2.実行結果

次の図に示すように、10431プロセスに4つのシグナルが送信され、プロセスは誰がシグナルを送信したかを示します(この時点で、女の子はブラックリストのボーイフレンドが数回電話をかけたことを知っています)

 

おすすめ

転載: blog.csdn.net/hml111666/article/details/123683046