APUE:信号

信号是系统用来异步通知一个进程某些事件发生了的机制。从效果上来说,有点像中断。信号发生时,打断原有执行过程,进入信号处理函数(如果注册了的话)或默认处理(忽略或终止程序),结束后恢复原有流程。默认情况下,信号处理过程中可能会被其它信号继续中断,所以需要考虑各种可能的情况,比如库函数重入的问题。信号处理函数执行的上下文是在原有栈帧基础上继续的,所以可以用 setjmp() 和 longjmp()。

一些常见的信号

  • SIGABRT
  • SIGALRM
  • SIGCHLD
  • SIGINT
  • SIGQUIT
  • SIGSEGV
  • SIGUSR1
  • SIGUSR2

注册信号处理函数

typedef void (*__sighandler_t) (int);__sighandler_t signal (int __sig, __sighandler_t __handler);

struct sigaction
  {
    union
      {
	/* Used if SA_SIGINFO is not set.  */
	__sighandler_t sa_handler;
	/* Used if SA_SIGINFO is set.  */
	void (*sa_sigaction) (int, siginfo_t *, void *);
      }
    __sigset_t sa_mask;
    int sa_flags;
  };

int sigaction (int __sig, const struct sigaction *__restrict __act, struct sigaction *__restrict __oact);

信号处理函数

#define SIG_ERR	((__sighandler_t) -1)		/* Error return.  */
#define SIG_DFL	((__sighandler_t) 0)		/* Default action.  */
#define SIG_IGN	((__sighandler_t) 1)		/* Ignore signal.  */

产生信号

int kill (__pid_t __pid, int __sig);
int raise (int __sig);
unsigned int alarm (unsigned int __seconds);
void abort (void);

int sigqueue (__pid_t __pid, int __sig, const union sigval __val);

信号集

int sigemptyset (sigset_t *__set);
int sigfillset (sigset_t *__set);
int sigaddset (sigset_t *__set, int __signo);
int sigdelset (sigset_t *__set, int __signo);
int sigismember (const sigset_t *__set, int __signo);

更多函数

// 进程阻塞直到有信号产生
int pause (void);

// 阻塞信号
int sigprocmask (int __how /* = SIG_BLOCK or SIG_UNBLOCK or SIG_SETMASK */, const sigset_t *__restrict __set, sigset_t *__restrict __oset);
// 获得未决(已产生但未递送)信号
int sigpending (sigset_t *__set);

// 修改信号屏蔽字然后阻塞直到有信号产生
// 与 sigprocmask() + pause() 相比,是原子操作
int sigsuspend (const sigset_t *__set);

sigsetjmp() 和 siglongjmp()

#define sigsetjmp(env, savemask)	__sigsetjmp (env, savemask)
void siglongjmp (sigjmp_buf __env, int __val);

与 setjmp() 和 longjmp() 相比,如果 savemask 不为 0,使用 siglongjmp() 跳出信号处理函数时会恢复信号屏蔽字。

中断的系统调用

ioctl()、read()、readv()、write()、writev() 针对低速设备(可能会被永远阻塞,如管道、终端、网络等)时可能会被信号打断,如果使用 sigaction() 设置信号处理函数并指定 SA_RESTART 时会重新启动,否则返回 -1 并设置 errno 为 EINTR。

其它概念

  • 要注意不可靠的信号,比如在安装信号处理函数后与调用等待函数之间,信号可能会发生。
  • 必须注意可重入函数,尤其是 malloc()、free() 等
时间: 2024-11-05 06:24:43

APUE:信号的相关文章

APUE信号-程序汇总

最近重看APUE,发现对于很多程序的要领还是没有完全理解,所以梳理下便于查看,而且有很多值得思考的问题. 程序清单10- 1  捕获 SIGUSR1 和 SIGUSR2的简单程序 #include "util.h" static void sig_usr(int); int main(void){ if(signal(SIGUSR1,sig_usr) == SIG_ERR) err_sys("cannot catch SIGUSR1!"); if(signal(SI

APUE: 信号相关系统调用和库函数

信号就是软件中断,信号提供一种处理异步事件的方法. 信号出现时按照下列方式处理: 1.忽略此信号,有两个信号不能忽略. 2.捕捉此信号,有两个信号不能被捕捉. 3.默认处理,少数默认处理是忽略,大部分默认处理是终止. ctrl+D组合键,不是信号,只是EOF字符 linux中1-31为普通信号:34-64为实时信号. trap-l 命令查看所有信号,64个 信号从1开始,没有0. SIGHUP:终端接口检测到连接断开发出该信号, SIGINT:ctrl+c,终端中断符,一般用来停止一个失去控制的

apue学习笔记(第十章 信号)

本章先对信号机制进行综述,并说明每种信号的一般用法. 信号概念 每个信号都有一个名字,这些名字都以3个字符SIG开头.在头文件<signal.h>中,信号名都被定义为正整形常量. 在某个信号出现时,可以按下列3种方式之一进行处理: 1 忽略该信号.大多数信号都可以使用这种方式进行处理,但有两种信号却决不能被忽略:SIGKILL和SIGSTOP(只能执行系统默认动作). 2 捕获信号.通知内核在某信号发生时,调用一个用户函数对这种时间进行处理. 3 执行系统默认动作.对于大多数信号的系统默认动作

APUE学习笔记——10 信号(一)——信号介绍

信号的基本概念 信号是软件中断,信号提供了解决异步时间的方法. 每一中信号都有一个名字,信号名以SIG开头. 产生信号的几种方式 很多条件可以产生信号: 终端交互:用户按下某一些按键,如ctl+c,会产生信号. 硬件异常:如除数为0,内存引用错误.    kill(2)函数:将信号发送到一个进程或者进程组   kill(1)命令:该命令为kill(2)函数的接口.用于终止失控的后台in成.  检测到某软件条件发生:如网络连接上传来外数据(产生SIGURG信号),闹钟超时(产生SIGALRM信号)

APUE学习笔记——10.11~10.13 信号集、信号屏蔽字、未决信号

如有转载,请注明出处:Windeal专栏 首先简述下几个概念的关系: 我们通过信号集建立信号屏蔽字,使得信号发生阻塞,被阻塞的信号即未决信号. 信号集: 信号集:其实就是一系列的信号.用sigset_t set表示. 数据类型:sigset_t 类似于整型(位数可能超过整型,因而不能用整型表示). 我们一般在sigprocmask()等函数中使用信号集,用于创建一系列进程要阻塞的信号,告诉内核不允许这些信号发生. 几个关于信号集的函数: #include <signal.h> int sige

APUE学习笔记——10信号——信号接口函数 signal 和 sigaction

signal函数 signal函数是早起Unix系统的信号接口,早期系统中提供不可靠的信号机制.在后来的分支中,部分系统使用原来的不可靠机制定有signal函数,如 Solaris 10 .而更多的系统采用新语义 可靠信号机制,如4.4BSD. 出于signal函数不同系统的不统一性,我们一般使用sigaction函数取代它.关于sigaction函数,我们在本文后面做详细介绍. 函数原型: #include <signal.h> void (*signal(int signo,void (*

【APUE】线程与信号

每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有线程共享的.进程中的信号是递送到单个线程的. 线程中pthread_sigmask函数类似与进程的sigprocmask函数,可以用来阻塞信号. #include <signal.h> int pthread_sigmask(int how,const sigset_t *set,sigset_t *obset); 线程可以通过调用sigwait等待一个或多个信号发生. #include <signal.h> int sigw

【APUE】信号

一.信号概念 信号都被定义为正整数,不存在编号为0的信号. 信号是异步事件的经典实例.产生信号的事件对进程而言是随机出现的,进程不能简单地测试一个变量来判别是否出现了一个信号,而是必须告诉内核在此信号出现时,请执行下列操作. 信号的处理有三种方式: 1.忽略此信号.大多数信号都可使用这种方式进行处理,SIGKILL和SIGSTOP不能被忽略,它们向超级用户提供了使进程终止或停止的可靠方法. 2.捕捉信号,通知内核在某种信号发生时调用一个用户函数.注意:不能捕捉SIGKILL和SIGSTOP信号

APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int kill(pid_t pid,int signo); int raise(int signo); Both return: 0 if OK,?1 on error kill向进程号为pid的进程发送signo信号 能够看出 以下两行代码是等价的: kill(getpid(), signo); raise(sig