Linux信

Linux信

信 是一种软件中断,它提供了一种处理异步事件的方法,也是进程间唯一的异步通信方式。在Linux系统中,根据POSIX标准扩展以后的信 机制,不仅可以用来通知某种程序发生了什么事件,还可以给进程传递数据。

两种方式:硬件方式和软件方式

二、哪些情况会引发信 /p>

1.键盘事件 ctrl+c ctrl+l

2.非法内存 如果内存管理出错,系统就会发送一个信 进行处理

3.硬件故障

4.环境切换:比如从用户态切换到其他态,状态的改变也会发送一个信 ,这个信 会告知给系统。

 

三.信 种类

kill -l  查看信 的种类

信 的值定义在signal.h中,在Linux中没有16和32这两个信 。

其中编 34以上的是实时信 (可靠信 ),34以下的是普通信 (不可靠信 )

通过案例观察信

out.sh

chmod u+x out.sh

./out.sh

另开一个终端

查找进程

ps -ef | head -n 1 ; ps -ef | grep “out.sh” | grep -v “grep”

进程ID是2774

kill给进程发信 ,9(SIGKILLL)信 是杀死进程

kill -9 2774

此时终端1中会看到killed,进程被杀死了

 

linux中的这64个信 各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有详细说明,在命令行输入man 7 signal:

四、可靠信 和不可靠信

信 的可靠性是指信 是否会丢失,或者说该信 是否支持排除。SIGHUP(1)~SIGSYS(31)之间的信 都是继承自UNIX系统是不可靠信 ,Linux系统根据POSIX标准定义了SIGRTMIN(33) ~ SIGRTMAX(64)之间的信 ,它们都是可靠信 ,也称为实时信 。

五、信 的处理

知道了什么是信 ,那么为什么有信 ,信 是谁发送给谁的呢,怎么发送/p>

信 的发送者很多,比如终端驱动程序,进程,系统。而接收者大多是一个进程。

进程收到此信 ,其可选的处理动作有以下三种:

  1. 忽略此信 (大多数信 可以使用这个方式来处理,但是有两种信 不能被忽略SIGKILL和SIGSTOP,因为他们向内核和超级用户提供了进程终止和停止的可靠方法,如果忽略了,那么这个进程就变成了没人能管理的进程,显然是内核设计者不希望看到的场景)
  2. 执行该信 的默认处理动作(终止该信 )对于每个信 来说,系统都对应默认的处理动作,当发生了该信 ,系统会自动执行。不过,对系统来说,大部分处理方式都比较粗暴,就是直接杀死该进程。
  3. 提供一个信 处理函数(自定义动作),要求内核在处理该信 时切换到用户态执行这个处理函数,这种方式称为捕捉一个信 。(即就是需要告诉内核,用户希望如何处理某一种信 ,说白了就是写一个信 处理函数,然后将这个函数告诉内核。当该信 产生时,由内核来调用用户自定义的函数,以此来实现某种信 的处理)

六.信 处理函数

1.signal()

函数原型:

#include<signal.h>

void (*signal(int signum,void(*handler))(int)))(int);

第一个参数指定信 的值,第二个参数指定针对前面信 值得处理,可以忽略该信 (参数设为SIG_IGN);课以采用系统默认方式处理信 (参数设为SIG_DFL);也可以自己实现处理方式(参数指定一个函数地址)

SIG_GIN:忽略信

SIG_DFL:恢复信 的默认行为

如果signal调用成功,返回最后一次为安装信 signum而调用signal()时的handler值,失败则返回SIG_ERR.

2.sigaction()

#include<signal.h>

int sigaction(int signum,const struct sigaction*act,struct sigaction *oldact));

sigaction函数用于改变进程接收到特定信 后的行为。

sigaction函数的第一个参数为信 的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信 (为这两个信 定义自己的处理函数,将导致信 安装错误)第二个参数是指向结构sigaction的一个实例指针,在结构sigaction的实例中,指定了对特定信 的处理,可以为空,进程会以缺省的方式对信 处理;第三个参数oldact指向的对象用来保存原来对相应信 的处理,可指定oldact为NULL。如果把第二个第三个参数都设为NULL,那么该函数可用于检查信 的有效性。

3、发送信 函数

(1) int raise(int sig);  对当前进程发送指定信

(2) int pause(void);  将进程挂起等待信

(3) int kill(pid_t pid,int sig); 通过进程编 发送信

 (4) unsigned int alarm(unsigned int seconds); 指定时间(秒)发送SIGALRM信 。 seconds 为0 时取消所有已设置的alarm请求;

 (5)int sigqueue(pid_t pid,int sig,const union sigval val);类似于kill函数,多了附带共用体 union sigval形数,将共用体中的成员 int sival_int 或 void *sival_ptr 的值传递给 信 处理函数中的定义类型 siginfo_t 中的 int si_int 或 void *si_ptr;

(6)int setitimer(int which,const struct itimerval *value,struct itimerval *oldvalue);  可定时发送信 ,根据which可指定三种信 类型:SIGALRM、SIGVTALRM 和 SIGPROF;作用时间也因which值不同而不同;struct itimerval 的成员 it_interval定义间隔时间,it_value 为0时,使计时器失效;

(7) void abort(void) 将造成进程终止;除非捕获SIGABORT信 ; 

4. 信 集及信 集操作

sigfillset(sigset_t *set); 设置所有的信 到set信 集中;

sigemptyset(sigset_t *set); 从set信 集中清空所有信 ;

sigaddset(sigset_t *set,int sig);在set信 集中加入sig信 ;

sigdelset(sigset_t *set,int sig);在set信 集中删除sig信 ;

5、阻塞信 相关函数

 int sigprocmask(int how,const sigset_t *set,sigset_t *set);  根据how值,设置阻塞信 集,或释放阻塞的信 集

 int sigpending(sigset_t *set); 获取在阻塞中的所有信 ;

 int sigsuspend(const sigset_t *set);    类似于 pause()函数!

七、信 处理函数的过程

(1)注册信 处理函数

 

信 的处理是由内核来代理的,首先程序通过sigal或sigaction函数为每个信 注册处理函数,而内核中维护一张信 向量表,对应信 处理机制。这样,在信 在进程中注销完毕之后,会调用相应的处理函数进行处理。

 

(2)信 的检测与响应时机

在系统调用或中断返回用户态的前夕,内核会检查未决信 集,进行相应的信 处理。

 

(3)处理过程:

程序运行在用户态时->进程由于系统调用或中断进入内核->转向用户态执行信 处理函数->信 处理函数完毕后进入内核->返回用户态继续执行程序

 

首先程序执行在用户态,在进程陷入内核并从内核返回的前夕,会去检查有没有信 没有被处理,如果有且没有被阻塞就会调用相应的信 处理程序去处理。首先,内核在用户栈上创建一个层,该层中将返回地址设置成信 处理函数的地址,这样,从内核返回用户态时,就会执行这个信 处理函数。当信 处理函数执行完,会再次进入内核,主要是检测有没有信 没有处理,以及恢复原先程序中断执行点,恢复内核栈等工作,这样,当从内核返回后便返回到原先程序执行的地方了。

参考图:

 

文章知识点与官方知识档案匹配,可进一步学习相关知识CS入门技能树Linux入门初识Linux24720 人正在系统学习中

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年7月6日
下一篇 2019年7月6日

相关推荐