博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux 信号(signal)
阅读量:4110 次
发布时间:2019-05-25

本文共 3003 字,大约阅读时间需要 10 分钟。

  • 信号是 UNIX 和 Linux 系统响应某些条件而产生的一个事件。接收到该信号的进程会相应的采取一些行动。我们用术语 生成 表示一个信号的产生,使用术语 捕获 表示接收到一个信号。
  • 信号是由于某些错误条件而生成的,如 内存段冲突 / 浮点处理器错误 或 非法指令等。它们由 shell 和终端处理器生成来引起中断,它们还可以作为在 进程间传递消息修改行为 的一种方式,明确地由一个进程发送给另一个进程
目录
  1. 信号列表
  2. 处理信号(使用 signal 函数
  3. 发送信号(使用键盘组合键 / 使用 kill 命令 / 使用 kill 函数)
  4. 处理信号(使用 sigaction 函数)(优先使用该函数)

1. 信号列表
信号名称 说明
SIGABORT * 进程异常终止
SIGALRM 超时警告
SIGFPE * 浮点运行异常
SIGHUP 连接挂断
SIGILL * 非法指令
SIGINT 终端中断
SIGKILL 终止进程(此信号不能被捕获或忽略
SIGPIPE 向无读进程的管道写数据
SIGQUIT 终端退出
SIGSEGV * 无效内存段访问
SIGTERM 终止
SIGUSR1 用户定义信号 1
SIGUSR2 用户定义信号 2
SIGCHLD 子进程已经停止或退出
SIGCONT 继续执行暂停进程
SIGSTOP 停止执行(此信号不能被捕获或忽略
SIGTSTP 终端挂起
SIGTTIN 后台进程尝试读操作
SIGTTOU 后台进程尝试写操作

(‘ * ’ 表示:系统对信号的响应视具体实现而定)


2. 处理信号(使用 signal 函数)
  1. signal 函数
#include 
void (*signal(int sig, void (*func)(int)))(int);
  1. 特殊的信号处理函数
名称 说明
SIG_IGN 忽略信号
SIG_DEL 恢复默认行为
  1. 实验代码如下(程序响应 SIGINT 终端中断信号,然后恢复到该信号的默认行为):
/* test2.c */#include 
#include
#include
#include
void handleSig(int);void main(){
printf("running...\n"); signal(SIGINT, handleSig); // 主进程循环,等待信号 while(1){
sleep(2); printf("alive.\n"); }}void handleSig(int sig){
printf("got signal: %d\n", sig); signal(SIGINT, SIG_DFL);}

运行程序,执行结果如下:

ubuntu@cuname:~/dev/beginning-linux-programming/test$ gcc -o test2 test2.cubuntu@cuname:~/dev/beginning-linux-programming/test$ ./test2running...alive.alive.^Cgot signal: 2 		// 第一次 响应 SIGINT 终端中断信号:打印字符串alive.alive.^C						// 第二次 响应,程序默认终止ubuntu@cuname:~/dev/beginning-linux-programming/test$

3. 发送信号(使用键盘组合键 / 使用 kill 命令 / 使用 kill 函数)
  1. 使用 kill 命令发送信号(格式为:‘kill 信号代码或信号名称 目标进程PID’)
ubuntu@cuname:~/dev$ kill -sigint 38897
  1. kill 函数(这个函数和同名的 kill 命令完成相同的功能
  • 想要发送一个信号,发送进程必须拥有相应的权限。这通常意味着两个进程必须拥有相同的用户 ID (即你只能发送信号给属于自己的进程,但超级用户可以发送信号给任何进程)
#include 
#include
int kill(pid_t pid, int sig);
  1. alarm 函数(闹钟功能)
  • alarm 函数用来在 seconds 秒之后安排发送一个 SIGALRM 信号。但由于处理的延时和时间调度的不确定性,实际闹钟时间将比预先安排的要稍微拖后一点儿。
  • 把参数 seconds 设置为 0 将取消所有已设置的闹钟请求。
  • 如果在接收到 SIGALRM 信号之前再次调用 alarm 函数,则闹钟重新开始计时。
  • 每个进程只能有一个闹钟时间
#include 
unsigned int alarm(unsigned int seconds);

使用 alarm 函数,实现进程自我唤醒,代码如下:

#include 
#include
#include
void handleSig(int);void main(){
printf("main running...\n"); // 响应/处理 SIGALRM 闹钟信号 signal(SIGALRM, handleSig); // 闹钟倒计时 5 秒 alarm(5); // 暂停执行,等待被 SIGALRM 闹钟信号唤醒 pause(); printf("done.\n");}void handleSig(int sig){
printf("wake up.\n");}

执行结果如下(达到预期目的):

ubuntu@cuname:~/dev/beginning-linux-programming/test$ gcc -o test2 test2.cubuntu@cuname:~/dev/beginning-linux-programming/test$ ./test2main running...wake up. 	// 被 SIGALRM 闹钟信号唤醒done.

4. 处理信号(使用 sigaction 函数)
  • signal 函数在传统的 UNIX 编程中很常见。但是 X/Open 和 UNIX 规范推荐了一个更新和更健壮的信号编程接口:sigaction
  1. sigaction 函数
#include 
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);

sigaction 结构定义在文件 signal.h 中,它的作用是定义在接收到参数 sig 指定的信号后应该采取的行动。该结构至少应该包括以下几个成员:

void (*) (int) sa_handler
sigset_t sa_mask
int sa_flags


转载地址:http://pclsi.baihongyu.com/

你可能感兴趣的文章
链睿和家乐福合作推出下一代零售业隐私保护技术
查看>>
Unifrax宣布新建SiFAB™生产线
查看>>
艾默生纪念谷轮™在空调和制冷领域的百年创新成就
查看>>
NEXO代币持有者获得20,428,359.89美元股息
查看>>
Piper Sandler为EverArc收购Perimeter Solutions提供咨询服务
查看>>
RMRK筹集600万美元,用于在Polkadot上建立先进的NFT系统标准
查看>>
JavaSE_day12 集合
查看>>
JavaSE_day14 集合中的Map集合_键值映射关系
查看>>
Day_15JavaSE 异常
查看>>
异常 Java学习Day_15
查看>>
JavaSE_day_03 方法
查看>>
day-03JavaSE_循环
查看>>
Mysql初始化的命令
查看>>
day_21_0817_Mysql
查看>>
day-22 mysql_SQL 结构化查询语言
查看>>
MySQL关键字的些许问题
查看>>
浅谈HTML
查看>>
css基础
查看>>
HTML&CSS进阶
查看>>
Servlet进阶和JSP基础
查看>>