UNIX环境编程学习笔记(23)——信号处理初步学习
2014-10-30 00:20
441 查看
lienhua34
2014-10-29
在计算机科学中,信号(英语:Signals)是 Unix、类 Unix 以及其他 POSIX 兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。
关于这段描述,我们可以从中学习到下面几点关于信号的知识,
1. 信号是什么:UNIX 进程间的一种异步通讯机制。
2. 信号的作用:提醒目标进程某事件的发生,并中断了目标进程正常的控制流程。
3. 进程对信号的处理:目标进程可以执行信号的默认处理函数,或者执行进程自定义的信号处理程序。
每个信号都有一个名字, 这些名字都以三个字符 SIG 开头。 例如,SIGABRT是夭折信号, 当进程调用 abort 函数时产生这种信号。SIGALRM 是闹钟信号,当由 alarm 函数设置的计时器超时后产生此信号。在 UNIX 系统中,这些信号都定义在头文件 <signal.h> 中,并且都是以一个正整数来表示(信号编号)。通过在 shell 中运行命令 kill -l 可以查看当前系统所执行的所有信号。
UNIX 系统规定了内核可以对信号执行以下三种处理行为,
1. 忽略此信号。有两个信号 SIGKILL 和 SIGSTOP 不可忽略,这两个信号提供给超级用户终止或停止进程的可靠方法。
2. 执行系统默认动作。大多数信号的默认动作是终止进程。
3. 捕获信号,执行用户自定义的处理函数。
#include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);
返回值:若成功则返回信号以前的处理配置,若出错则返回SIG_ERR
其中,参数 func 的值可以是,
• 常 量SIG_IGN, 向 内 核 表 示 忽 略 此 信 号 (有 两 个 信 号 SIGKILL 和SIGSTOP 不可忽略,调用 signal 函数会报错)。
• 常量SIG_DFL,表示执行信号的系统默认动作。
• 一个函数指针,表示信号发生时执行该函数进行处理,这个函数称为信号处理程序。信号处理函数接收一个 int 类型的信号值参数,无返回值。
signal 信号的返回值也是一个函数指针,指向该信号之前的信号处理程序。
下面我们来看一个例子,
killdemo.c
上面的 killdemo.c 程序文件中,父进程为信号 SIGUSR1 和 SIGUSR2设置了信号处理程序sig_usr。然后调用 fork 创建一个子进程,子进程的信号 SIGUSR1 和 SIGUSR2 的信号处理程序继承父进程的,同样是sig_usr(除非子进程调用了 exec 函数,子进程中这两个信号的信号处理动作才会设置为系统默认)。父进程调用 kill 函数向子进程发送信号 SIGUSR1,而调用 raise 函数向自身发送信号 SIGUSR2. 编译该程序,生成并执行 killdemo文件,
通过上面的运行结果,可以看到父进程 3261 创建了子进程 3262,父进程 3261 捕获了信号 SIGUSR2,子进程捕获了信号 SIGUSR1。实际运行结果与预期结果相符合。
(done)
2014-10-29
1 信号的概念
维基百科中关于信号的描述是这样的:在计算机科学中,信号(英语:Signals)是 Unix、类 Unix 以及其他 POSIX 兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。
关于这段描述,我们可以从中学习到下面几点关于信号的知识,
1. 信号是什么:UNIX 进程间的一种异步通讯机制。
2. 信号的作用:提醒目标进程某事件的发生,并中断了目标进程正常的控制流程。
3. 进程对信号的处理:目标进程可以执行信号的默认处理函数,或者执行进程自定义的信号处理程序。
每个信号都有一个名字, 这些名字都以三个字符 SIG 开头。 例如,SIGABRT是夭折信号, 当进程调用 abort 函数时产生这种信号。SIGALRM 是闹钟信号,当由 alarm 函数设置的计时器超时后产生此信号。在 UNIX 系统中,这些信号都定义在头文件 <signal.h> 中,并且都是以一个正整数来表示(信号编号)。通过在 shell 中运行命令 kill -l 可以查看当前系统所执行的所有信号。
UNIX 系统规定了内核可以对信号执行以下三种处理行为,
1. 忽略此信号。有两个信号 SIGKILL 和 SIGSTOP 不可忽略,这两个信号提供给超级用户终止或停止进程的可靠方法。
2. 执行系统默认动作。大多数信号的默认动作是终止进程。
3. 捕获信号,执行用户自定义的处理函数。
2 设置信号处理程序
UNIX 系统提供了 signal 函数来设置信号的处理程序,#include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);
返回值:若成功则返回信号以前的处理配置,若出错则返回SIG_ERR
其中,参数 func 的值可以是,
• 常 量SIG_IGN, 向 内 核 表 示 忽 略 此 信 号 (有 两 个 信 号 SIGKILL 和SIGSTOP 不可忽略,调用 signal 函数会报错)。
• 常量SIG_DFL,表示执行信号的系统默认动作。
• 一个函数指针,表示信号发生时执行该函数进行处理,这个函数称为信号处理程序。信号处理函数接收一个 int 类型的信号值参数,无返回值。
signal 信号的返回值也是一个函数指针,指向该信号之前的信号处理程序。
下面我们来看一个例子,
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <signal.h> #include <unistd.h> static void sig_usr(int); int main(void) { pid_t pid; if (signal(SIGUSR1, sig_usr) == SIG_ERR) { printf("can't catch SIGUSR1: %s\n", strerror(errno)); exit(-1); } if (signal(SIGUSR2, sig_usr) == SIG_ERR) { printf("can't catch SIGUSR2: %s\n", strerror(errno)); exit(-1); } if ((pid = fork()) < 0) { printf("fork error: %s\n", strerror(errno)); exit(-1); } else if (pid == 0) { pause(); exit(0); } printf("process %d creates a child process %d\n", getpid(), pid); sleep(1); kill(pid, SIGUSR1); waitpid(pid, NULL); raise(SIGUSR2); exit(0); } static void sig_usr(int signo) { if (signo == SIGUSR1) { printf("process %d received SIGUSR1\n", getpid()); } else if (signo == SIGUSR2) { printf("process %d received SIGUSR2\n", getpid()); } else { printf("process %d received signal: %d\n", getpid(), signo); } }
killdemo.c
上面的 killdemo.c 程序文件中,父进程为信号 SIGUSR1 和 SIGUSR2设置了信号处理程序sig_usr。然后调用 fork 创建一个子进程,子进程的信号 SIGUSR1 和 SIGUSR2 的信号处理程序继承父进程的,同样是sig_usr(除非子进程调用了 exec 函数,子进程中这两个信号的信号处理动作才会设置为系统默认)。父进程调用 kill 函数向子进程发送信号 SIGUSR1,而调用 raise 函数向自身发送信号 SIGUSR2. 编译该程序,生成并执行 killdemo文件,
lienhua34:demo$ ./killdemo process 3261 creates a child process 3262 process 3261 received SIGUSR2 process 3262 received SIGUSR1
通过上面的运行结果,可以看到父进程 3261 创建了子进程 3262,父进程 3261 捕获了信号 SIGUSR2,子进程捕获了信号 SIGUSR1。实际运行结果与预期结果相符合。
(done)
相关文章推荐
- UNIX环境编程学习笔记(23)——信号处理初步学习
- UNIX环境编程学习笔记(25)——信号处理进阶学习之 sigaction 函数
- UNIX环境编程学习笔记(24)——信号处理进阶学习之信号集和进程信号屏蔽字
- UNIX环境编程学习笔记(24)——信号处理进阶学习之信号集和进程信号屏蔽字
- UNIX环境编程学习笔记(25)——信号处理进阶学习之 sigaction 函数
- unix 环境编程学习笔记------对于信号的一点认识
- UNIX环境编程学习笔记(1):——出错处理errno
- UNIX环境编程学习笔记(1):——出错处理errno
- Unix信号处理学习笔记
- Unix环境高级编程学习笔记整理
- UNIX环境编程学习笔记(6)——文件I/O之判断文件类型
- Unix环境高级编程 学习笔记_1_Unix 基础知识
- UNIX环境编程学习笔记(7)——文件I/O之文件访问权限与进程访问控制
- Unix 网络编程 学习笔记一 环境搭建
- Unix环境高级编程 第二章 学习笔记
- UNIX环境编程学习笔记(10)——文件I/O之硬链接和符号链接
- Unix环境高级编程笔记 :10、信号
- UNIX环境编程学习笔记(8)——文件I/O之校验当前登录用户对文件的访问权限
- UNIX环境编程学习笔记(2)——文件I/O之不带缓冲的 I/O
- 【linux高级环境编程学习笔记二】信号通信