厦门移动网站建设哪家专业,国内有哪些顶尖的设计公司,wordpress主题主页面,注册360建筑网平台进程信号 一、信号1、概念2、系统定义的信号列表3、常见的信号处理方式 二、产生信号的方式1、终端按键#xff08;1#xff09;组合键#xff08;2#xff09;示例代码#xff08;3#xff09;运行结果 2、调用系统函数#xff08;1#xff09;kill命令#xff08;21组合键2示例代码3运行结果 2、调用系统函数1kill命令2kill函数【1】函数【2】描述 3raise函数【1】函数【2】描述 4abort函数【1】函数【2】描述 3、软件条件1alarm函数2描述3示例代码4运行结果 4、硬件异常 三、阻塞信号1、概念2、信号在内核中的示意图3、解释 四、信号集1、sigset_t1定义2应用 2、信号集操作函数1函数2描述3返回值 3、sigprocmask函数1函数2描述3参数how的有效值 4、sigpending函数1函数2描述 5、示例代码 五、信号捕捉1、捕捉信号1概念2过程示意图 2、signal函数1函数2描述 3、sigaction函数1函数2描述 4、可重入函数1概念 六、SIGCHLD信号 一、信号
1、概念
在Linux中用于进程间通信和控制的一种机制是进程之间事件异步通知的一种方式属于软中断。所有信号的产生最终都要由OS来进行执行因为OS是进程的管理者。信号的处理可以不立即处理而在合适的时候再处理。它有一个时间窗口在这个时间窗口内必须记住信号的到来。尽管进程没有收到信号它也要知道对合法信号的处理操作这属于进程内置功能的一部分。
2、系统定义的信号列表 每个信号都有一个编号和一个宏定义名称这些宏定义可以在signal.h中找到。编号34以下的信号为普通信号编号34及以上的信号为实时信号。信号 SIGKILL 和 SIGSTOP 无法被捕获或者忽略。
3、常见的信号处理方式
SIG_IGN忽略信号。SIG_DFL执行信号的默认处理动作。捕捉信号提供一个信号处理函数要求内核在处理该信号时切换到用户态执行这个处理函数。
二、产生信号的方式
1、终端按键
1组合键
Ctrl c信号2SIGINT。Ctrl \信号3SIGQUIT。
2示例代码
void handler(int signo)
{cout get a signo: signo endl;
}int main()
{for(int i 1; i 31; i){signal(i, handler);}while(true){cout I am a crazy process pid getpid() endl;sleep(1);}return 0;
}3运行结果 2、调用系统函数
1kill命令
命令行输入kill -signo pid
2kill函数
【1】函数 【2】描述
kill函数即系统调用可用于向任何进程或进程组发送任何信号。如果 pid 为正数则将 sig 信号发送到 pid 指定的进程。如果 pid 等于 0则 sig 信号将发送到调用进程的进程组中的每个进程。如果 pid 等于 -1则 sig 信号将发送到调用进程有权发送信号的每个进程但进程1init除外。如果 pid 小于 -1则 sig 将发送到进程组中 ID 为 -pid 的每个进程。如果 sig 为 0则不发送信号但仍执行错误检查。这可用于检查进程 ID 或进程组 ID 是否存在。
3raise函数
【1】函数 【2】描述
raise函数向调用进程或线程发送 sig 信号。在单线程程序中它等价于 kill(getpid(), sig);在多线程程序中它等价于 pthread_kill(pthread_self(), sig);如果信号有自定义的处理函数则raise函数只有在该函数返回后才会返回。
4abort函数
【1】函数 【2】描述
abort函数首先取消 SIGABRT 信号的阻塞状态然后为调用它的进程引发该信号。 而这会导致进程异常终止除非 SIGABRT 信号被捕获并且信号处理程序自定义的信号处理方法没有返回。如果abort函数导致进程终止则关闭并刷新所有打开的流。如果 SIGABRT 信号被忽略或被返回的处理程序自定义的信号处理方法捕获则 abort函数仍将终止进程。 它通过恢复 SIGABRT 的默认配置然后再次引发该信号来实现此目的。
3、软件条件
1alarm函数 2描述
alarm函数安排在seconds秒后将 SIGALRM 信号传送到调用进程。如果秒数为零则取消任何挂起的警报。在任何情况下任何先前用alarm函数设置的“闹钟”都会被取消。alarm函数的返回值为如果没有先前安排的“闹钟”则返回零反之返回距离任何先前安排的“闹钟”发出 SIGALRM 信号的剩余秒数。
3示例代码
void handler(int signo)
{cout get signo: signo endl;unsigned int n alarm(5);cout 剩余时间 n endl;
}int main()
{signal(SIGALRM, handler);alarm(50);while(true){cout this process pid: getpid() endl;sleep(1);}return 0;
}4运行结果 4、硬件异常
硬件异常被硬件以某种方式检测到并通知内核然后内核向当前进程发送适当的信号。
三、阻塞信号
1、概念
信号递达Delivery执行信号的处理动作。信号未决Pending信号从产生到递达之间的状态。信号阻塞Block被阻塞的信号产生时将保持在未决状态直到进程解除对该信号的阻塞才能执行递达的动作即只要信号被阻塞就不会递达。
2、信号在内核中的示意图 3、解释
标志位block是信号阻塞标志位pending是信号未决1表示设置0表示未设置。函数指针表handler是信号的处理方法。信号产生时内核在进程控制块中设置该信号的未决标志置1直到信号递达才清除该标志置0。在上方的图中SIGHUP信号产生过但是被阻塞了所以暂时不能递达当它递达时执行默认处理动作SIGINT信号未产生过且被阻塞了当产生SIGINT信号时该信号将会被阻塞即pending只将该信号的位置置为1而不会递达。它的处理动作是忽略但在没有解除阻塞之前不能忽略这个信号。因为进程仍有机会改变处理动作之后再解除阻塞。SIGQUIT信号未阻塞也未产生过它的处理动作是用户自定义函数sighandler。在Linux中常规信号在进程解除阻塞之前如果产生过多次则在递达之前只计一次。而实时信号如果在递达之前产生过多次可以依次放在一个队列里即实时信号的每一次产生都有效。
四、信号集
1、sigset_t
1定义 2应用
在标志位block和pending中每个信号只有一个bit的标志即非0即1不会记录对应信号产生的次数。sigset_t信号集阻塞block和未决pending标志可以用它来存储这个类型可以表示每个信号的“有效”或“无效”状态。在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。阻塞信号集也叫做当前进程的信号屏蔽字Signal Mask。
2、信号集操作函数
1函数 2描述
sigemptyset将 set 给出的信号集初始化为空即将所有的信号都从集合中排除。sigfillset将 set 初始化为 full即将所有信号都设置在内。sigaddset添加 set 中signum对应的信号。sigdelset删除 set 中signum对应的信号。sigismember测试 signum 是否是 set 的成员即测试 signum 是否在set 中。sigset_t 类型的对象必须通过调用 sigemptyset 或 sigfillset 进行初始化然后才能传递给函数 sigaddset、sigdelset和 sigismember或者下面描述的其他 glibc 函数sigisemptyset()、sigandset() 和 sigorset()。 如果不这样做结果是未定义的。
3返回值
sigemptyset、sigfillset、sigaddset 和 sigdelset 成功时返回 0错误时返回 -1。对于sigismember来说如果 signum 是 set 的成员则返回 1如果 signum 不是 set 的成员则返回 0错误时返回 -1。出错时这些函数会设置 errno 以指示原因。
3、sigprocmask函数
1函数 2描述
sigprocmask函数用于获取和/或更改调用线程的信号掩码。sigprocmask函数调用的行为取决于 how 的值。如果 oldset 为非 NULL则信号掩码的上一个值将存储在 oldset 中。如果 set 为 NULL则信号掩码保持不变即忽略 how但信号掩码的当前值仍通过 oldset 返回如果它不是 NULL。
3参数how的有效值
SIG_BLOCK阻塞信号集将被设置为当前信号集和参数 set 的并集即将 set 中包含的信号都阻塞。SIG_UNBLOCK参数 set 集合中的信号将从当前受阻信号集中移除即 set 中包含的信号将被设置为不阻塞。 允许尝试解锁未被阻塞的信号。SIG_SETMASK将阻塞信号集的内容设置为参数 set 的内容。
4、sigpending函数
1函数 2描述
sigpending函数返回等待传送到调用线程的信号集即在被阻塞时引发的信号。挂起信号的掩码在参数set中返回。
5、示例代码
#includeiostream
#includeunistd.h
#includesignal.h
using namespace std;void PrintSignal(const sigset_t pending)
{for(int i 31; i 1; --i){if(sigismember(pending, i))cout 1;elsecout 0;}cout \n endl;
}int main()
{sigset_t bset, oset;sigemptyset(bset);sigemptyset(oset);for(int i 1; i 31; i){sigaddset(bset, i);}sigprocmask(SIG_SETMASK, bset, oset);sigset_t pending;sigemptyset(pending);while(true){int ret sigpending(pending);if(ret -1)continue;PrintSignal(pending);sleep(1);}return 0;
}五、信号捕捉
1、捕捉信号
1概念
如果信号的处理动作是用户自定义函数在信号递达时就调用这个函数。当我们的进程从内核态返回到用户态的时候进行信号的检测和处理。
2过程示意图 2、signal函数
1函数 2描述
signal函数的行为在 UNIX 版本中各不相同在不同版本的 Linux 中也存在差异。signal函数将 signum 信号的处置处理方法设置为处理程序handler该处理程序是SIG_IGN、SIG_DFL或自定义函数handler的地址。如果 signum 信号被传送到进程则会发生以下情况之一。如果处置处理方法设置为 SIG_IGN则忽略该信号如果处置设置为 SIG_DFL则发生与该信号关联的默认操作如果处置设置为自定义函数handler则首先将处置重置为 SIG_DFL或者信号被阻止然后使用参数 signum 调用处理程序handler。 如果调用处理程序导致信号被阻塞则信号在从句柄handler返回时被解除阻塞。signal函数返回值为当调用成功时返回信号处理程序的上一个值失败则返回SIG_ERR并设置errno用来指示错误原因。
3、sigaction函数
1函数 2描述
sigaction系统调用用于更改进程在接收到特定信号时所采取的操作。signum指定信号可以是除 SIGKILL 和 SIGSTOP 之外的任何有效信号。如果 act 为非 NULL则signum信号的处理操作设置为 act 中sa_handler设定的操作。 如果 oldact 为非NULL则signum信号的上一个处理操作保存在 oldact 中。在某些涉及联合体的体系结构中不要同时分配设置给sa_handler和sa_sigaction。sa_restorer元素已过时不应使用。 POSIX 未指定 sa_restorer 元素。sa_handler指定要与 signum 关联的操作可以设置为SIG_DFL默认操作、SIG_IGN忽略操作或指向信号处理函数的指针此函数接收信号编号作为其唯一参数。通过用自定义函数就可以用同一个函数处理多种信号即它是一个回调函数不过不是被main函数调用而是被系统所调用。sa_mask指定在执行信号处理程序期间应阻止的信号掩码即添加执行信号到调用信号处理程序的线程的信号掩码中除了当前信号被自动屏蔽之外也可以通过设置它来自动屏蔽另外一些信号。 此外触发处理程序的信号将被阻止除非使用 SA_NODEFER 标志。当某个信号的处理函数被调用时内核自动将当前信号加入进程的信号屏蔽字当信号处理函数返回时自动恢复原来的信号屏蔽字。这样就保证了在处理某个信号时如果这种信号再次产生那么它会被阻塞到当前处理函数执行结束为止。
4、可重入函数
1概念
如果一个函数被重复进入的情况下出错或者可能出错则为不可重入函数。反之为可重入函数。
六、SIGCHLD信号
子进程在终止时会给父进程发SIGCHLD信号该信号的默认处理动作是忽略父进程可以自定义SIGCHLD信号的处理函数。父进程自定义SIGCHLD信号的处理函数这样父进程只需专心处理自己的工作不必关心子进程。当子进程终止时会通知父进程然后父进程在信号处理函数中调用wait相关函数清理子进程这是解决僵尸问题的一种方法前提是父进程不提前退出。父进程调用sigaction将SIGCHLD的处理动作设置为SIG_IGN。这样用fork函数创建出来的子进程在终止时会被自动清理掉而不会产生僵尸进程和通知父进程。系统默认的忽略动作和用户用sigaction函数自定义的忽略通常是没有区别的。但这是一个特例此方法对于Linux可用但不保证在其它类UNIX系统上都可用。 本文到这里就结束了如有错误或者不清楚的地方欢迎评论或者私信 创作不易如果觉得博主写得不错请点赞、收藏加关注支持一下