信号----进阶总结:

总结:

信号:

信号的生命周期:信号的产生-》在进程中注册-》在进程中注销-》信号处理

信号的产生:

硬件长产生:Ctrl+c 中断信号 Ctrl+|      Ctrl +z进程停止

软件产生:kill -[signum]  就是上面信号的数字(这些数字就是宏) -p pid (向指定进程发送指定信号)

系统调用接口 man 2 kill,----->int kill(pid_t pid, int sig);

 

 

信号在进程中的注册:在进程pcb中做标记,标记进程收到了哪些信息

task_struct结构体中,有个sigpending(未决),

我们把信号加入到进程的过程称为

注册

 

 

 

 

非可靠信号:pcb中pending位图中是否注册,是,就不做任何操作。不是就注册

可靠信号:pcb都进行注册

 

注销

信号在进程中的注销

    非可靠信号:节点只有一个,注销就是删除节点,位图置0

    可靠信号:节点有多个,删除一个节点,要判断是否有相同信号节点。如果没有就信号置0.如果还有就不处理位图。

信号的处理

信号的处理并不是立即被处理;而是选择 一个合适的实际进行处理信号。当进程运行从内核态返回用户态的时候,就会去执行这个信号。

        问题:进程如何从用户态切换到内核态:发起系统调用;程序异常;中断(硬件中断Ctrl+c);

        进程当前运行的代码是用户或者是库函数,就说进程当前运行在用户态

信号的处理方式:

        默认的处理方式--既定义好的处理方式

        忽略处理方式--处理动作什么都不做

        自定义处理方式--用户自己定义的处理方式----修改默认的处理函数(自定义一个处理函数去替换默认的处理函数)

如何修改信号的处理方式:

   1   、  sighandler_t    signal(int signum    ,sighander_t  handler);

信号会打断当前的阻塞操作

                    signum :信号的编码 ---替换signum这个信号的处理函数(也可以是信号名,信号名和数字是宏,可以替换)

                    handler:函数指针 用户传入的处理函数

                        SIG_DFL:信号的默认处理动作(default)

                        SIG_IGN:信号的忽略处理动作(ignore)

                        typedef void(*sighandler_t)(int);//定义了一个函数指针类型,这个函数指针类型是*sighandler_t,返回值是void,参数是int

          

  1 #include <unistd.h>

  2 #include <stdio.h>

  3 #include <signal.h>

  4#include<stdlib.h>                                                                                                  

  5

  6 int main (){

  7   signal(SIGINT, SIG_IGN);  // 也可以换成signal(2, 3);  2号信号被替换成3号信号

  8   while(1){

  9     printf("xiuxiyihui\n");

10     sleep(10);

11   }

12   system("pasue");

13   return 0;

14 }

 

 

2、int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);  将信号signum结构被后面的*act结构替换,同时将signum的结构保存到*oldact结构中

 

 

struct sigaction {

               void     (*sa_handler)(int);   ---->参入的参数是现有的信号数字,并对现有信号进行处理

               void     (*sa_sigaction)(int, siginfo_t *, void *);      //这两个其实是一个联合体,二选一运用

               sigset_t   sa_mask;    ------>当我们正在处理这个信号时,sa_mask形成一个阻塞,别的信号不能处理

sigset_t   sa_mask;这里的sigset是个位图结构,由于这个位图是直接从内存中分配来的,他原来的信息需要清空才能保证我们使用位图时的正确性

               int        sa_flags;      -->这是一个标识,通常标记为0,就是使用上面sa_handler函数;标记为SA_SIGINFO,就是使用sa_sigaction的函数

               void     (*sa_restorer)(void);

           };

 

 1 #include <unistd.h>                                                                                                  

 2 #include <stdio.h>

 3 #include <signal.h>

 4 #include <stdlib.h>

 5

 6 int main (){

 7  

 8   struct sigaction new_act, old_act;

 9   new_act.sa_flags = 0;

10   new_act.sa_handler = SIG_IGN;

11

12 // int sigemptyset(sigset_t *set)  清空信号的集合

13   sigemptyset(&new_act.sa_mask);//清空的是结构体中的位图

14   sigaction(2, &new_act, &old_act);

15

16   while(1){

17     printf("xiuxiyihui\n");

18     sleep(10);

19   }

自定义信号在对操作函数的改变上可以传入已经定义好的信号,也可以直接传入函数指针就可以

1 #include <unistd.h>                                                                                                  
2 #include <stdio.h>
3 #include <signal.h>
4 #include <stdlib.h>
5
6 void rec(int signo){
7   signal(signo, SIG_DFL);
8   printf("%d已经恢复\n",signo);
9 }
10
11
12 
13 int main (){
14  //1 signal(SIGINT, SIG_IGN);
15   struct sigaction new_act, old_act;
16   new_act.sa_flags = 0;
17   new_act.sa_handler = rec;
18
19   sigemptyset(&new_act.sa_mask);//清空的是结构体中的位图
20
21   sigaction(2, &new_act, &old_act);
22
23   while(1){
24     printf("xiuxiyihui\n");
25     sleep(10);
26   }
27   system("pasue");
28   return 0;
29 }     

信号的阻塞

阻止信号被抵达--》阻止信号被处理

信号可以注册,但是不被处理(进程信号中位图置1,链表里加入了信号,)

在pcb中还有一个阻塞信号集合【标记哪些信号不被处理】

 

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

        how:

                SIG_BLOCK 向阻塞集合中加入set集合中的信号block = mask | set

                SIG_UNBLOCK 把阻塞的集合中移除set集合中的信号 block = mask &(~set)

                SIG_SETMASK 将set集合信号设置为阻塞集合 block= set

        oldset:

            用于保存修改前的信号

关键函数

            sigfillset(sigset_t *set)向set中添加所有信号

            sigaddset(sigset_t* set, int signum)向set中添加指定信号

 

在所有的信号中,9号信号SIGKILL和19号信号SIGSTOP不可以阻塞,他们不能加入到block中进行阻止

调研sleep函数的实现

 

 

可重入和不可重入

 

 

函数的重入:

            可重入:多个执行流程同时执行进入相同的函数

            不可重入: 多个执行流程同时执行进入相同的函数,有可能造成数据的二义性以及代码逻辑混乱

当用户设计一个函数或者使用一个函数时,在多个执行流中,这个时候就要考虑函数是否允许重入

 

函数的可重入和不可重入关键是:

             这个函数中是否对临界资源(全局数据)进行来非原子操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值