linux之信号

信号:在生活中,我们遇到过不同种类的信号,比如:(交通信号,乃至某个人的表情,动作等带给你不同的信号)然而,在我们的linux下,我们最熟悉的就是,当遇到一个死循环的程序时,我们第一想到的就是按ctrl+c,此时这个进程立马终止,这是一种通过键盘产生的信号。而说起ctrl+c,就引出了前台进程和后台进程。当ctrl+c产生的信号只能发给前台进程。

用kill -l命令就可以查看信号了;


产生信号的另一种方式是:信号异常触发系统使该进程终止:

例子:

运行结果:



还有一种方式,通过指令来使该进程终止


然后直接运行./test:



还有一种方式,通过alarm使进程终止

说起alarm给大家举个例子吧,alarm意思是闹钟,在这里也同样代表着当你执行某个进程时,突然用alarm定时的时间到了,这时闹钟发挥了作用,使得你的进程被迫停止,比如:


这是一个统计1秒钟计数的程序,当一秒钟到时,就会被SIGALRM信号终止。

运行结果:


下面我们来说一下处理信号的几种方式吧!

忽略信号;执行默认;执行自定义(信号的捕捉)三种方式。(那么问题来了,什么时候处理呢?答案是适当的时候处理大笑


执行信号的处理动作称为信号递达,信号从产生到递达之间的状态,称为信号未决。进程可以选择阻塞某个信号,被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略则是在递达之后可选的一种处理动作。

信号在内核中是这样表示的:


block:代表屏蔽状态字(1表示阻塞,0表示不阻塞)

pending:代表未决(1表示未决,0表示可以递达)

handler:代表信号的处理方式(默认,忽略,自定义)

每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。

上面那张表说明:SIGHUP是没有阻塞也没有产生,所以处理动作为默认处理动作

SIGINT的block为1,pending也为1,表示正在阻塞,无法递达。它的处理动作为忽略,但是在没有解除阻塞之前不能忽略该信号,很可能在解除阻塞前改变为其他的处理动作。

对于上述的三张表,操作系统中的每个进程运行时都会存在。

SIGQUIT的block为1,pending为0,说明正在被阻塞,解除阻塞后就可以递达。处理动作为用户自定义的处理动作。

还有一种现象是,对于解除阻塞之前可能会发送多次信号,这时操作系统该作何处理呢。这里主要是分为普通信号和实时信号,普通信号出现发送多次的情况,会当做是一次信号进行处理。而实时信号发送多次的情况,会将这多个信号存在一个队列中,分别处理各个信号。我们一般讨论的是普通信号,因此只记录一次,我们将未决和阻塞状态用同一个数据类型来存储sigset_t,信号集为sigset_t。还需要注意的一点是,阻塞信号集也叫做当前进程的信号屏蔽字。

说了信号集,我们之前说过这些普通信号是以位图的形式存放的。每一个bit位表示一种信号是否存在。

对于信号的操作,我们有一组信号集操作函数,如下:


函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信号。

函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表⽰示 该信号集的有效信号包括系统支

持的所有信号。

在使⽤用sigset_t类型的变量之前,⼀一定要调 ⽤用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。

做完初始化之后调用sigaddset和sigdelset来添加或者删除信号。

这四个函数成功返回0,失败返回-1;

sigismember用来表示某种信号是否出现在有效信号集中。出现返回1,不出现返回0.

*还有函数sigprocmask:(读取或更改进程的信号屏蔽字)

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

成功返回0,出错返回-1

这里的oset为输出型参数,如果oset为非空,则输出当前进程的信号屏蔽字,通过oset输出。如果set为非空,则更改信号屏蔽字,how指示如何更改。如果set和oset都为非空,则将当前进程的信号屏蔽字备份在oset中,然后再通过how参数更改信号屏蔽字。

how主要有三种表示:SIG_BLOCK(包含了我们希望添加的信号屏蔽字),SIG_UNBLOCK(包含了我们希望从信号屏蔽字中阻塞的信号),SIG_SETMASK(设置了当前的信号屏蔽字的值);

*函数sigpending:(读取当前进程的未决信号集)

#include <signal.h>
int sigpending(sigset_t *set);

set为输出型参数,将信号通过set输出

 小栗子:

#include<stdio.h>
#include<signal.h>void PrintSigset(sigset_t *sig)
{int i = 0;for(i = 1; i < 32; i++){if(sigismember(sig,i)){printf("1 ");}else{printf("0 ");}}printf("\n");
}int main()
{sigset_t sigset,osigset;sigemptyset(&sigset);sigemptyset(&osigset);sigaddset(&sigset,SIGINT);sigprocmask(SIG_BLOCK,&sigset,&osigset);while(1){sigpending(&sigset);PrintSigset(&sigset);sleep(1);}return 0;
}
这个程序实现了将2号信号设置为阻塞信号。所以一直无法递达。

程序运行时,每秒钟把各信号的未决状态打印一遍,由于我们阻塞了SIGINT信号,按Ctrl-C将会使SIGINT信号处于未决

状态,按Ctrl-\和ctrl+z仍然可以终止程序,因为SIGQUIT信号没有阻塞。

运行结果:


还有一个小栗子,我们将2号信号阻塞之后,5秒后解除阻塞。并打印原来信号的状态。

#include<stdio.h>
#include<signal.h>void PrintSigset(sigset_t *sig)
{int i = 0;for(i = 1; i < 32; i++){if(sigismember(sig,i)){printf("1 ");}else{printf("0 ");}}printf("\n");
}void handler(int sig)
{printf("pid: %d sig:%d \n",getpid(),sig);
}
int main()
{sigset_t sigset,osigset;sigemptyset(&sigset);sigemptyset(&osigset);sigaddset(&sigset,SIGINT);sigprocmask(SIG_BLOCK,&sigset,&osigset);int count = 0;signal(2,handler);//signal(2,SIG_DFL);while(1){sigpending(&sigset);PrintSigset(&sigset);sleep(1);if(count++ > 5){sigprocmask(SIG_SETMASK,&osigset,NULL);count = 0;}}return 0;
}

运行结果:




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/382709.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频解析有感,在解析 iqiyi与qq视频的时候,记录一些发现

最近对iqiyi与qq视频解析发现&#xff0c;两个网站的解析流程&#xff0c;尤其是反解析措施 各有特点&#xff0c;简单记录一下 先说iqiyi&#xff0c; 浏览器模拟移动端可以拿到视频的mp4链接&#xff0c;这个不多说。 iqiyiPC端浏览器获取 ts过程&#xff1a; a.iqiyi一次性…

C语言atoi函数的用法

#include < stdlib.h > int atoi(const char *nptr);用法&#xff1a;将字符串里的数字字符转化为整形数。返回整形值。 注意&#xff1a;转化时跳过前面的空格字符&#xff0c;直到遇上数字或正负符号才开始做转换&#xff0c;而再遇到非数字或字符串结束时(’/0’)才…

[Linux]继续探究mysleep函数(竞态条件)

之前我们探究过mysleep的简单用法&#xff0c;我们实现的代码是这样的&#xff1a; #include<stdio.h> #include<signal.h>void myhandler(int sig) {}unsigned int mysleep(unsigned int timeout) {struct sigaction act,oact;act.sa_handler myhandler;sigempt…

C语言的atoi和C++的to_string

to_stringint to string将其他型转换成字符串型atoiascii to integer是把字符串转换成整型数的一个函数 to_string #include <iostream> // std::cout #include <string> // std::string, std::to_stringint main () {std::string perfect std::to_string…

ubuntu 升级python3.5到python3.7,并升级pip3

1, 下载python3.7.tgz 文件&#xff0c;解压&#xff0c; 2. 编译安装 3. 删除 /usr/bin 目录下的 pip3, python3 4. 建立新的软连接&#xff1a; #添加python3的软链接ln -s /usr/local/python3/bin/python3.7 /usr/bin/python3#添加 pip3 的软链接ln -s /usr/local/python3/b…

[Linux]死锁

死锁是指多个进程在运行过程中因争夺资源而造成的一种僵局&#xff0c;当进程处于这种僵持状态时&#xff0c;若无外力作用&#xff0c;它们都将无法再向前推进。之前信号量的时候我们知道&#xff0c;如果多个进程等待&#xff0c;主要体现在占有锁的问题上。死锁也可以被定义…

Python安装第三方模块总结 转载的

转自 https://www.jellythink.com/archives/541

[C++]vector创建二维数组

c.resize(n);将c重置为大小为n个元素向量&#xff0c;如果n比原来的元素多&#xff0c;则多出的元素常被初始化为0//节选《面向对象的程序设计》杜茂青 int N5, M6; vector<vector<int> > Matrix(N); for(int i 0; i< Matrix.size(); i){ Matrix[i].resize(M…

[Linux]线程安全和可重入函数

线程安全&#xff1a;一个函数被称为线程安全的&#xff0c;当且仅当被多个并发进程反复调用时&#xff0c;它会一直产生正确的结果。如果一个函数不是线程安全的&#xff0c;我们就说它是线程不安全的。 重入&#xff1a;函数被不同的控制流程调用,有可能在第一次调用还没返回…

[Linux]信号量

信号量是一个计数器&#xff0c;用于为多个进程提供对共享数据对象的访问。 在信号量上只有三种操作可以进行&#xff0c;初始化、递增和增加&#xff0c;这三种操作都是原子操作。递减操作可以用于阻塞一个进程&#xff0c;增加操作用于解除阻塞一个进程。 为了获得共享资源…

Linux VIM 程序中有游离的‘\357’ ‘\274’错误

gcc date.cpp -o date -lstdc date.cpp:18:20: 错误&#xff1a;程序中有游离的‘\357’date.Showdata()&#xfffd;&#xfffd;&#xfffd;^ date.cpp:18:21: 错误&#xff1a;程序中有游离的‘\274’date.Showdata()&#xfffd;&#xfffd;&#xfffd;^ date.cpp:18:22…

[Linux]关于SIGCHLD

之前我们就学过&#xff0c;关于wait和waitpid来处理僵尸进程&#xff0c;父进程等待子进程结束后自己才退出&#xff0c;这样的方法有俩种方式&#xff0c;一种是父进程死死的等子进程退出&#xff0c;也就是使用阻塞的方式等待子进程退出&#xff0c;另一种方式是通过非阻塞的…

C语言思维导图

本人能力有限&#xff0c;知识点难免概括不全&#xff0c;如有错误欢迎指正

转载一篇关于curl的文章

转载一篇关于curl的文章 http://www.360doc.com/content/16/0107/15/18578054_526158476.shtml

[Linux]vi/vim下添加多行注释和取消注释

添加注释&#xff08;Centos&#xff09;&#xff1a; 在命令行模式下按ctrlV进入 visual block模式&#xff08;可视化模式&#xff09; 选中你需要注释的行&#xff0c;再按大写的I&#xff0c;输入//&#xff0c;最后按俩下esc即可。 如果想让前进tab个位&#xff0c;则可在…

pthread和互斥量条件变量函数意义速查表

数据类型 pthread_t 线程 互斥量和条件变量

[Linux]共享内存

共享内存是UNIX提供的进程间通信手段中速度最快的一种&#xff0c;也是最快的IPC形式。为什么是最快的呢&#xff0c;因为数据不需要在客户进程和服务器进程之间复制&#xff0c;所以是最快的一种IPC。这是虚存中由多个进程共享的一个公共内存块。 两个不同进程A、B共享内存的…

僵尸进程的产生,危害和解决方案

概念 僵死状态&#xff08;Zombies&#xff09;是一个比较特殊的状态。 当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程。僵尸进程会以终止状态保持在进程表中&#xff0c;并且会一直在等待父进程读取退出状态代码。所以&#xff0c;只要子进程退出&…

CString string 转换

https://www.cnblogs.com/HappyEDay/p/7016162.html

[Linux]gdb调试多进程多线程例程

gdb相信学linux的同学已经比较熟悉了吧&#xff0c;它是linux下代码调试工具。我们在写c语言&#xff0c;c的代码时经常会用到&#xff0c;它有一些常用的调试命令: run&#xff08;r&#xff09;&#xff1a;运行程序&#xff0c;如果有断点在下一个断点处停止 start&#xf…