苏州建设职业技术学院招聘信息网站,tp做网站签到功能,zencart添加wordpress,如何做企业网站文章目录 1.信号的概念1.1基本概念1.2信号的处理基本概念1.3信号的发送与保存基本概念 2.信号的产生2.1信号产生的五种方式2.2信号遗留问题(core,temp等) 3.信号的保存3.1 信号阻塞3.2 信号特有类型 sigset_t3.3 信号集操作函数3.4 信号集操作函数的使用 4.信号的处理4.1 信号的… 文章目录 1.信号的概念1.1基本概念1.2信号的处理基本概念1.3信号的发送与保存基本概念 2.信号的产生2.1信号产生的五种方式2.2信号遗留问题(core,temp等) 3.信号的保存3.1 信号阻塞3.2 信号特有类型 sigset_t3.3 信号集操作函数3.4 信号集操作函数的使用 4.信号的处理4.1 信号的捕捉4.2 深入理解地址空间4.3 如何理解系统调用4.4 sigaction对信号捕捉 5.可重入函数6.编译器的优化及volatile关键字7.SIGCHLD信号(子进程退出发的信号) 1.信号的概念
1.1基本概念 所谓同步和异步就是 比如我正在上课我让一个学生去帮我拿快递然后我停下等那个学生回来再继续讲即同步。 如果学生去拿快递我不管他我接着讲就是异步 1-31号为普通信号 34-64号实时信号 1.2信号的处理基本概念
信号的处理大致分为三种 a.默认动作 b.忽略动作 c.自定义处理—信号的捕捉 coretemp都是终止在本篇文章的后面会有更详细的介绍
1.3信号的发送与保存基本概念 2.信号的产生
2.1信号产生的五种方式
信号产生的三种主要方式和两种不常用接口
如果把所有信号都捕捉换成自定义动作那么怎么办 答操作系统有些信号是不允许自定义捕捉的比如9号信号killed。如果所有信号都能被捕捉那不乱套了而且信号的发送者只有一个那就是操作系统发的通过位图来执行
下面还有两种信号产生的方式 4.软件条件 5.异常 我们都知道进程发生异常了就会崩溃然后就会退出。 这便是异常发送信号 那么崩溃了为啥会退出因为异常的默认动作是终止进程 那么可以不退出嘛可以的我们可以自定义捕捉异常但是不推荐这么做
2.2信号遗留问题(core,temp等) 我们用一个多进程的例子再来看看标志位
3.信号的保存
3.1 信号阻塞 3.2 信号特有类型 sigset_t 从上图来看,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。 阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。 3.3 信号集操作函数
#include signal.hint sigemptyset(sigset_t *set); 把sigset_t 这个位图全部清空int sigfillset(sigset_t *set); 把整个位图全部置1int sigaddset (sigset_t *set, int signo); 把一个特定的信号signo设置到这个集合里(置1)int sigdelset(sigset_t *set, int signo); 把一个特定的信号signo在这个集合里清除(置0)int sigismemberconst sigset_t *set, int signo); 判断一个信号是否在集合中以及两个系统调用函数
3.4 信号集操作函数的使用 #include iostream
#include unistd.h
#include cstdio
#include sys/types.h
#include sys/wait.hvoid PrintPending(sigset_t pending)
{std::cout curr process[ getpid() ]pending: ;for (int signo 31; signo 1; signo--){if (sigismember(pending, signo)){std::cout 1;}else{std::cout 0;}}std::cout \n;
}void handler(int signo)
{std::cout signo 号信号被递达!!! std::endl;std::cout ------------------------------- std::endl;sigset_t pending;sigpending(pending);PrintPending(pending);这里正在处理handler方法的时候把pending再获取一次如果这时候打印出来的pending信号为1就说明只能把handler方法处理完才能清空如果这时候打印出来的pending信号为全0就说明在进入handler方法之前就把1清零了std::cout ------------------------------- std::endl;
}int main()
{// 0. 捕捉2号信号signal(2, handler); // 自定义捕捉2号信号默认操作是退出所以我们要自定义捕捉否则推出了就看不到后面的现象了。// 1. 屏蔽2号信号sigset_t block_set, old_set;sigemptyset(block_set);sigemptyset(old_set);sigaddset(block_set, SIGINT); // 我们有没有修改当前进行的内核block表呢1 0// 1.1 设置进入进程的Block表中sigprocmask(SIG_BLOCK, block_set, old_set); // 真正的修改当前进行的内核block表完成了对2号信号的屏蔽int cnt 15;while (true){// 2. 获取当前进程的pending信号集sigset_t pending;sigpending(pending);// 3. 打印pending信号集PrintPending(pending);cnt--;// 4. 解除对2号信号的屏蔽if (cnt 0){std::cout 解除对2号信号的屏蔽!!! std::endl;sigprocmask(SIG_SETMASK, old_set, block_set);}sleep(1);}
}4.信号的处理
4.1 信号的捕捉 4.2 深入理解地址空间 4.3 如何理解系统调用 4.4 sigaction对信号捕捉 5.可重入函数 main函数调用insert函数向一个链表head中插入节点node1,插入操作分为两步,刚做完第一步的时候,因为硬件中断使进程切换到内核,再次回用户态之前检查到有信号待处理,于是切换到sighandler函数,sighandler也调用insert函数向同一个链表head中插入节node2,插入操作的两步都做完之后从sighandler返回内核态,再次回到用户态就从main函数调用的insert函数中继续往下执行,先前做第一步之后被打断,现在继续做完第二步。结是,main函数和sighandler先后向链表中插入两个节点,而最后只有一个节点真正插入链表中了 像上例这样,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入,insert函数访问一个全局链表,有可能因为重入而造成错乱,像这样的函数称为不可重入函数。
6.编译器的优化及volatile关键字 7.SIGCHLD信号(子进程退出发的信号) 要想不产生僵尸进程还有另外一种办法:父进程调 用sigaction将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。