【APUE | 10】函数signal
函数signal
函数signal介绍
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signal函数
作用1:站在应用程序的角度,注册一个信号处理函数
作用2:忽略信号,设置信号默认处理 信号的安装和回复
参数
--signal是一个带signum和handler两个参数的函数,准备捕捉或屏蔽的信号由参数signum给出,接收到指定信号时将要调用的函数有handler给出
--handler这个函数必须有一个int类型的参数(即接收到的信号代码),它本身的类型是void
--handler也可以是下面两个特殊值:① SIG_IGN 屏蔽该信号 ② SIG_DFL 恢复默认行为
SIGCHLD信号
通过 signal(SIGCHLD, SIG_IGN) 通知内核对子进程的结束不关心,由内核回收。
- 如果不想让父进程挂起,可以在父进程中加入一条语句: signal(SIGCHLD, SIG_IGN); 表示父进程忽略SIGCHLD信号。
- SIGCHLD信号:该信号是子进程退出的时候向父进程发送的。 子进程结束时, 父进程会收到这个信号。
如果父进程没有处理这个信号,也没有等待(wait)子进程,子进程虽然终止,但是还会在内核进程表中占有表项,这时的子进程称为僵尸进程。这种情 况我们应该避免(父进程或者忽略SIGCHILD信号,或者捕捉它,或者wait它派生的子进程,或者父进程先终止,这时子进程的终止自动由init进程 来接管)。
1. 测试代码
//忽略,屏蔽信号
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h> int main(int arg, char *args[])
{
pid_t pid=fork();
if(pid == -)
{
printf("fork() failed! error message:%s\n",strerror(errno));
return -;
}
//注册信号,屏蔽SIGCHLD信号,子进程退出,将不会给父进程发送信号,因此也不会出现僵尸进程
signal(SIGCHLD,SIG_IGN);
if(pid > )
{
printf("father is runing !\n");
sleep();
}
if(pid == )
{
printf("i am child!\n");
exit();
}
printf("game over!\n");
return ;
}
2. 测试代码
//恢复信号
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h> void catch_signal(int sign)
{
switch (sign)
{
case SIGINT:
printf("ctrl + C 被执行了!\n");
//exit(0);
break;
}
} int main(int arg, char *args[])
{
//注册终端中断信号
signal(SIGINT, catch_signal);
char tempc = ;
while ((tempc = getchar()) != 'a')
{
printf("tempc = %d\n", tempc);
//sleep()
}
//恢复信号
signal(SIGINT, SIG_DFL);
while ()
{
pause();
}
printf("game over!\n");
return ;
}
输出结果:

不可靠信号
一、缺陷一:
int sig_int();
...
signal(SIGINT, sig_int); /*①1establish handler*/
...
sig_int()
{
signal(SIGINT, sig_int); //②为了捕捉下一个信号
...
./*process the signal ... */
...
}
二、缺陷二:
信号对进程的控制能力差: 早期系统实现中,当我们不希望信号发生时,进程无法关闭一个 信号,并在记录它的发生。
很多时候我们有这样的需求,我们不希望信号打断某项的工作,但是当工作执行完后,又希望系统告诉我们这段时间内发生了什么信号。比如我们运行一段程序,要求运行完之前不能中断它(比如我们的Ctl+C),这是就需要暂时关闭这个信号。 首先我们明确需求,我们需要的是,信号暂时不起作用,并在之后能够提醒我们信号发生过。
int sig_int(); /* my signal handling function */
int sig_int_flag; /* set nonzero when signal occurs */
main()
{
signal(SIGINT, sig_int); /* establish handler */
...
while (sig_int_flag == )
pause(); /* go to sleep, waiting for signal */
...
}
sig_int()
{
signal(SIGINT, sig_int); /* reestablish handler for next time */
sig_int_flag = ; /* set flag for main loop to examine */
}
sig_int只有两行代码,它的作用就是忽略信号,并且用sig_int_flag标志信号发生过。
可重入函数
1.测试代码
#include<stdio.h>
#include<signal.h> int value = ; void fun() {
int i = ;
while (i++<) {
value++;
printf("value is %d\n", value);
sleep();
}
}
int main()
{
signal(, fun);
fun();
printf("the value is %d\n", value);
return ;
}
输出结果:


参考资料
【APUE | 10】函数signal的更多相关文章
- APUE学习笔记——10信号——信号接口函数 signal 和 sigaction
signal函数 signal函数是早起Unix系统的信号接口,早期系统中提供不可靠的信号机制.在后来的分支中,部分系统使用原来的不可靠机制定义signal函数,如 Solaris 10 .而 ...
- 初涉JavaScript模式 (10) : 函数 【进阶用法】
写在前面 不知不觉写到第10篇了.这篇写起来很忐忑,终于和高级搭上边了(呵呵),这篇我们 主要 说一下 JS 方法的部分高级用法(我知道的),笔者水平有限,难免有错.废话不多少,进入正文. 初始化 我 ...
- 转:函数signal()
from:http://blog.sina.com.cn/s/blog_4b226b92010119l5.html 当服务器close一个连接时,若client端接着发数据.根据TCP协议的规定,会收 ...
- day 10函数二
今日内容 '''实参:调用函数,在括号内传入的实际值,值可以为常量.变量.表达式或三者的组合*****形参:定义函数,在括号内声明的变量名,用来接受外界传来的值''''''注:形参随着函数的调用 ...
- python note 10 函数变量
1.命名空间 #内置命名空间 —— python解释器 # 就是python解释器一启动就可以使用的名字存储在内置命名空间中 # 内置的名字在启动解释器的时候被加载进内存里#全局命名空间 —— 我们写 ...
- Day 10 函数的形参,实参
今日内容 '''实参:调用函数,在括号内传入的实际值,值可以为常量.变量.表达式或三者的组合*****形参:定义函数,在括号内声明的变量名,用来接受外界传来的值''''''注:形参随着函数的调用 ...
- day 10 函数名的运用,闭包,迭代器
函数名的本质 函数名本质上就是函数的内存地址 函数名的五种运用: 1.函数名是一个变量 def func(): print(666) print(func) # 函数的内存地址 <functio ...
- Python 入门基础10 --函数基础3 函数对象、名称空间、装饰器
今日内容 1.函数对象 2.名称空间与作用域 3.函数的嵌套调用与闭包 4.装饰器 一.函数对象 1.1 定义 函数名存放的就是函数地址,所以函数名也就是对象,称之为函数对象 1.2 函数对象的应用 ...
- 从零开始的Python学习Episode 10——函数
函数 一.函数的创建 简单格式 def function_name(参数表): 函数体 return 如果没有写return,函数会默认返回一个none 二.函数的参数 必需参数: 调用函数时必需参数 ...
随机推荐
- 在 github 新建一个文件夹
创建新文件的时候名字后面加个斜杠(/)就可以了.
- 设置MyBatis在控制台打印SQL语句
在调试阶段,打印SQL会极大方便开发者.MyBatis有提供配置,只需要在MyBatis的配置文件mybatis-config.xml中<configuration>节点下,添加如下配置: ...
- Spring Boot 启动过程及 自定义 Listener等组件
一.启动过程 二.自定义组件 package com.example.jdbc.listener; import org.springframework.context.ApplicationCont ...
- node之常用模块
http express cheerio superagent url events fs util querystring request
- CF28D Don't fear, DravDe is kind
传送门 题意:\(n\)个位置,每个位置有价值\(v_i\)和重量\(p_i\),要选出一些位置,如果要选位置\(i\),那么前面选的重量之和要为\(l_i\),后面选的重量之和要为\(r_i\),求 ...
- luogu P1052 过河
传送门 容易想到设\(f_i\)表示走到坐标\(i\)的最少走过的石子数 但是这题数据范围很大,,, 不过一次可以走的步数范围是1-10,石子个数最多100个,所以中间会有很多多出来的没石子的路,可以 ...
- sql server 查询某个时间段共有多少周及每周的日期段
sql 语句 as wknum,dateadd(wk,number,'2017-01-01') as firstday, (,, then '2017-12-31' ,,'2017-01-01')) ...
- HTML5中<template>标签的详细介绍
HTML5中<template>标签的详细介绍(图文) 这篇文章主要介绍了HTML5中的template标签,是HTML5入门中的重要知识,需要的朋友可以参考 一.HTML5 templa ...
- 【Gradle】Gradle环境配置
Windows环境 下载 作者下载的是gradle-4.1-all.zip,下载地址:http://services.gradle.org/distributions 环境配置 GRADLE_HOME ...
- Python sys.path详细介绍
如何将路径“永久"添加到sys.path? sys.path是python的搜索模块的路径集,是一个list 复制代码 代码如下: ['', 'C:\\WINDOWS\\system32\\ ...