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つのシグナルが送信され、プロセスは誰がシグナルを送信したかを示します(この時点で、女の子はブラックリストのボーイフレンドが数回電話をかけたことを知っています)