Linuxカスタム信号

4185 ワード

信号は同様にプロセス通信に用いられ、彼は非同期通信方式である.私たちの前のパイプはそうではありません.明らかに、リードプロセスはパイプの中にデータがあるのを待たなければなりません.そうしないと、彼は待たなければなりません.信号処理は異なり、プロセスはいつ信号が来るか分からないので、まず小さなコードを見て、信号のプログラムを見てみましょう.
[root@liumengli signal]# cat ./signal_recive1.c 
#include "stdio.h"
#include "signal.h"
#include "sys/types.h"
#include "unistd.h"

void new_op(int, siginfo_t *, void *);

int main(int argc, char**argv) {
        struct sigaction act; // 
        struct sigaction old_act; // , 
        int sig; // , 
        sig = atoi(argv[1]);

        sigemptyset(&act.sa_mask);
        act.sa_flags = SA_SIGINFO;
        act.sa_sigaction = new_op; // 

        if(sigaction(sig, &act, &old_act) < 0) { // 
                printf("install sigal error
"); return 1; } while(1) { // sleep(2); printf("Now we wait for signal
"); } } void new_op(int signum, siginfo_t * info, void * myact) { // printf("recive signal %d
", signum); exit(1); }

[root@liumengli signal]# ./signal_recive1 15
(私たちは15番の信号を新しい信号の信号量として、私たちは間もなく15を送信して目標のプロセスに良いことに注意して、私たちはここでシステムの15番の信号を使ったことに注意して、この信号は書くことができて、しかし2つの信号KILLとSTOPの信号があって、KILLの信号は9で、STOPはハードウェアの構造の体系によって異なって、彼らは書くことができなくて、原因は、カーネルのコードの中でインストールの信号の上でこのような1句(act&&&&&(sig == SIGKILL || sig == SIGSTOP))) return -EINVAL;同時に、彼らは遮蔽されない、すなわち応答されないことができず、他の信号は遮蔽されることができる.これは,カーネル設計者がプロセス制御に残る最後の下限を与えるために,ほとんどの信号のデフォルト動作がプロセスを終了し,この2つは名前から1つが終了し,もう1つが一時停止していることがわかるためである.このように我々が1つのプロセスに対して少なくとも最後の殺し方をするのは、プロセスにこの2つの信号を送信することであり、どのようにして後で見ることができるか)Now we wait for signal Now we wait for signal Now we wait for signal Now we wait for signal
.......
別の端末を開く
[root@liumengli signal]# ps -le ......
0 S     0 30681 28333  0  75   0 -   352 hrtime pts/2    00:00:00 signal_recive1 0 R     0 30828 28245  0  78   0 -  1368 -      pts/1    00:00:00 ps [root@liumenglisignal]#kill-15 30681このプロセスに支配されている端末の反応を見てみましょう
Now we wait for signal recive signal 15 [root@liumenglisignal]#私たちの予想通りに終わりました.
 
まずkill命令を説明します.これは信号を送信する命令です.もちろん、関数(linuxで提供しました)を使って、15番の信号を送信しました.予想通りに終わりました.通常、killはプロセスを殺すと考えられていますが、実はそうではありません.それはあなたに指定されたプロセスを送信することです.ほとんどのプロセスはシステムの信号量を変更しないと思います.もし本当に変更したら、STOPとKILLの2つの信号量を変更できません.私は変更しました.実行時に信号のインストールに失敗しました.もしあなたが1つのごろつきのプロセスを殺すことができないならば、kill-KILLの目標のプロセスのPIDを試してみてください、kill-STOPはとても面白い信号で、試してみて、回復したいならkill-CONTを送信します.もう1つ、linux/unix環境のプログラミングを書いたことがある人ははっきり知っていて、プロセスが準備ができていないとしても、送信信号はそれを緒状態に変えることができて、これは送信信号のソースコードを見て知っています.彼はターゲットプロセスを準備キューに掛けます.睡眠プロセスも信号に応答します
 
私のプログラムから、私は信号が来るかどうかを検出するコードがどこにもないことがわかりました.ユーザーは信号がいつ来るかに関心を持っていません.ユーザーは信号が来て私が何をすべきかに関心を持っています.では、誰が信号が来たかどうかを検出します.言い換えれば、信号検出のコードはどこに書いてありますか.それは
217 ret_with_reschedule: 218 cmpl $0,need_resched(%ebx) 219 jne reschedule 220 cmpl $0,sigpending(%ebx) 221 jne signal_return
このコードの220行目は検出信号であり、以前はプロセススケジューリングを見たことがあり、プロセススケジューリングコードは218行に書かれています.このコードは、システム呼び出しの戻り、割り込みの戻り、異常処理の戻りを含む、ユーザ空間に戻るときに実行されます.
 
もしあなたのプログラムがずっとユーザー空間にあり、いかなる中断も受けられない場合(実現不可能であり、少なくともタイミングのクロック中断は嫌がらせを受け、システム呼び出しのサポートがなく、直接自分でハードウェアを操作することも不可能である)、信号は応答されません.
 
応答の観点から言えば、私が信号を送るのではなく、相手がすぐに反応し、その間に遅延があるのは理解にかたくない.
少し整理してから:
#include <stdio.h>
#include <stdlib.h>
#include "signal.h"
#include "sys/types.h"
#include "unistd.h"

void my_action(int signum, siginfo_t * info, void * myact)
{ // 
        printf("recive signal %d
", signum); } void CreateSigAndBind(int Sig,void (*fun)(int signum, siginfo_t * info, void * myact)) { struct sigaction act; // struct sigaction old_act; // , sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; act.sa_sigaction = fun; // if(sigaction(Sig, &act, &old_act) < 0) { // printf("install sigal error
"); return ; } } int main(int argc, char**argv) { CreateSigAndBind(43,&my_action); CreateSigAndBind(44,&my_action); while(1) { // sleep(2); printf("Now we wait for signal
"); } return 1 ; }