`
xiangxji
  • 浏览: 58539 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Unix信号学习 ( 转 )

阅读更多

信号是传送给进程的一种事件通知,生成信号的事件有三大类:

1.       程序错误:除零,非法内存访问…

2.       外部信号:终端Ctrl-C产生SGINT信号,定时器到期产生SIGALRM…

3.       显示请求:kill函数允许进程发送任何信号给其他进程或进程组。

信号生成既可以是同步的(信号与程序中的某个具体操作相关并在那个操作同时产生),也可以是异步的。通常程序错误生成信号为同步的,进程显式请求给自己的信号也是同步的。

外部事件总是异步的,来自其他进程的显示请求也是异步的。

信号发生时,我们可以告诉unix内核采取下面三种动作中的任一种:

1.       忽略信号:大部分信号可被忽略,除SIGSTOP和SIGKILL信号外(这是超级用户杀掉或停掉任意进程的手段)。

2.       捕获信号:注册信号处理函数,它对产生的特定信号做处理。

3.       让信号默认动作起作用:unix内核定义的默认动作,有5种情况:

a)         流产abort:终止进程并产生core文件。

b)        终止stop:终止进程但不生成core文件。

c)         忽略:忽略信号。

d)        挂起suspend:挂起进程。

e)         继续continue:若进程是挂起的,则resume进程,否则忽略此信号。

任意时刻,进程可以为信号指定动作。

信号处理涉及两个过程,生成与交付。

信号生成出现在事件发生时,此时内核检查接收进程的相关数据结构,此结构中记录了信号的布局,悬挂信号集和处理动作。如果信号是要被忽略的,内核不做任何动作就返回。否则,将此信号加入悬挂信号集合中。(悬挂信号集合通常用位串表示,每位对应一个信号,内核无法记录同一信号的多个实例)。

       如果进程处于可中断的睡眠状态,并且该信号非阻塞,内核唤醒进程。被唤醒进程一旦运行则在返回用户态前优先处理悬挂信号,当有悬挂信号并且非阻塞时,内核查看是否有处理句柄,如果没有注册句柄,则采取默认动作(通常为终止进程)。如果有句柄,则将此信号加入阻塞信号屏蔽中。

       最后内核安排进程返回到用户态并执行信号句柄,同时保证句柄执行完时,进程从被中断处代码执行。

       由异步事件产生的信号可能在任一条指令后发生,当信号句柄完成时,进程从中断之处起执行。如果信号是在进程处于系统调用期间到达的,内核通常abort此系统调用并返回错误码EINTR。

       进程可以有选择的阻塞信号交付,当一个被阻塞的信号生成时,如果进程指定的动作为默认或者捕获,则此信号一直悬挂于该进程直到对此信号的阻塞放开,或者信号动作改为忽略。 系统对阻塞信号的判定是在信号交付时而非生成时,这样可以允许进程在信号被交付前改变信号动作。

       每个进程有一个阻塞信号屏蔽,它定义当前被阻塞交付的那些信号。可认为它是一个位串,每位对应一个信号。如果某信号对应的位被设置,则该信号当前阻塞,进程可调用

sigprocmask函数来检查或设置屏蔽。


 

程序错误类信号:默认动作使进程流产,产生core文件。

SIGABRT:   调用abort函数生成的信号。

SIGFPE:      浮点计算错误。

SIGILL:      非法指令错误。

SIGBUS/SIGSEGV: 硬件错误-非法地址访问。

SIGEMT:    硬件错误

SIGSYS:       非法系统调用。

SIGTRAP:   硬件错误(通常为断点指令)。

程序终止类信号:默认动作使进程终止,我们通常要处理这类信号,做一些清理工作,句柄函数应在结束时为此信号指定默认动作,然后再次生成该信号,使得程序终止。

SIGHUP:终端断开连接时,生成此信号给控制进程。

SIGINT:Ctrl-C或Delete按下时,由终端驱动生成,并发送给前台进程组中的所有进程。

SIGKILL:使程序立即终止,不能被捕获或忽略,也不能被阻塞。

SIGQUIT:Ctrl-\,如SIGINT,并且产生core。

SIGTERM:该信号使程序终止,但是可以阻塞、捕获、忽略。

闹钟类信号:通知定时器到期,默认动作是终止程序,但通常会设置句柄。

SIGALRM:alarm/setitimer函数设置定时到期后,会产生此信号。

SIGPROF:

SIGVTALRM:

I/O类信号:通知进程在描述字上发生了感兴趣事件,支持信号驱动IO。

SIGIO: fd准备执行输入输出时发送此信号。

SIGPOLL:异步I/O信号。

SIGURG:网络收到带外数据时可选择生成此信号。

作业控制类信号:

SIGCHLD:   进程终止或停止时会向其父进程发送该信号,默认动作为忽略。

SIGCONT:     使停止的进程恢复运行。

SIGSTOP:      停止进程。

SIGTSTP/SIGTTIN/SIGTTOU:

操作错误类信号:默认动作终止程序。

SIGPIPE:    管道破裂。

SIGXCPU/SIGXFSZ:

signal函数:

void (* signal(int sig, void (*func)(int)))(int);

sig指明是哪一种信号。

func指明动作:SIG_DFL, SIG_IGN,或者信号句柄地址。

当信号发生时,如果func指向信号句柄,系统在将控制转往句柄前,先将该信号动作置为DFL,或者阻塞该信号直到句柄完成。

Signal函数返回值指向前一次有效动作指针:SIG_DFL,SIG_IGN,或信号地址,这提供了恢复信号动作的机制。 如果signal调用出错,返回SIG_ERR并设置errno。

进程初启时的信号动作:

fork:继承父进程的动作

exec:所有信号动作要么是忽略要么是默认。

不可靠信号:

早期版本Unix中使用signal,每当信号交付时,其动作总是由系统重置为默认动作,因此为了使信号句柄执行期间,仍能对同一信号后续做反应,需要再次调用signal。

Catch_Signal(){

       // 如果第二次信号刚好在此时发生,将导致进程终止core掉。

       signal(SIGQUIT,Catch_Signal);

}

Main(){                   

       signal(SIGQUIT, Catch_Signal);

       …

}

使用signal的另一个问题是,对于信号,进程要么忽略,要么捕获,无法在一段时间内阻塞信号(推迟信号的交付),为了克服signal兼容性问题,现代unix均实现了POSIX定义的sigaction函数,该函数采用一个sigaction结构,除定义信号交付时要采取的动作外,还包含其他一些动作控制信息。

sigaction还允许调用进程检测或指定与特定信号相关的动作。

int sigaction(int sig, const struct sigaction* act, struct sigaction* oact);

sig指定信号-除SIGKILL和SIGSTOP。

如果act为NULL,则不改变信号动作,只查询当前动作。

成功返回0,失败则不安装新信号动作,返回-1,设置errno。

struct sigaction{

       void (*sa_handler)(int);                        // 同signal的第二参数func。          

       void (*sa_sigaction)(int, siginfo_t*, void*); // 仅当flags设置SA_SIGINFO起作用。

       sigset_t sa_mask;    // 指明信号执行期间要阻塞的一组信号,除此之外导致信号句柄执

行的信号也自动阻塞,除非指定了SA_NODEFER。信号句柄正常返回时,屏蔽恢复到原先状态。          

       int sa_flags;           //

};

sa_flags是一个位串,可以通过或运算生成。可设置下列标志:

SA_NOCLDSTOP: 只对CHLD信号起作用,子进程暂停时不发信号给父进程。

SA_RESTART: 信号句柄返回时,自动恢复被该信号中断的系统调用。否则该系统调用将中断返回-1,并设置errno为EINTR。

SA_ONSTACK:

SA_RESETHAND:信号句柄入口,系统将重置信号动作为SIG_DFL.

SA_NODEFER:句柄执行期间,不自动阻塞该信号。

SA_NOCLDWAIT:只对CHLD起作用,调用进程的所有子进程在终止时不会成为Zombe。这种情况下,父进程无需要wait子进程,并且子进程终止也不向父进程发SIGCHLD信号。

如果父进程调用wait,将阻塞到所有子进程终止,并返回-1,errno设为ECHILD.

SA_SIGINFO:如果未设置此标志,则信号句柄原型为:

 void func(int signo);

如果设置此标志,则句柄原型为:

void func(int signo, singinfo_t* info, void* context);

Info- 解释信号生成的原因。

Context-信号被交付时所中断进程的上下文。

一旦用sigaction为特定信号建立了动作,该动作就一直保持,直到另一次调用sigaction,或者调用exec,或者因设置了SA_RESETHAND导致系统自动改变动作为默认为止。

除了外部中断产生信号外,程序可以显式的调用raise函数给他自己发送信号,或调用kill向自己或其他进程发送信号。

阻塞信号意味着保持该信号并推迟它的交付,可以防止程序中的关键代码被信号中断。

信号集操作:

int sigemptyset(sigset_t* set); // 清空信号集

int sigfillset(sigset_t* set);   // 包含所有信号集

sigaddset/sigdelset/sigismember;

sigprocmask用来检测或改变调用进程的信号屏蔽。

int sigprocmask(int how, const sigset_t* set, sigset_t* oset);

How: SIGBLOCK SIG_UNBLOCK   SIG_SETMASK

如果调用sigprocmask放开某个信号而导致任何悬挂信号被解除阻塞,则函数返回前,这些信号中至少有一个被交付。

检查悬挂信号:int sigpending(sigset_t* set);

等待信号:int pause(void);

悬挂调用进程直到有一个信号到达。仅当句柄执行并返回时,pause函数才返回:此时返回-1,并设置errno为EINTR。所有其他情况下pause不返回。

如果多个相同信号在信号句柄运行前发给了进程,则句柄只被运行一次。换句话说,默认情况下unix信号是非排队的,只有当实现支持实时信号并且sa_flags设置SA_SIGINFO时,由sigqueue生成的后续信号才排队。

I/O执行期间,有可能到达信号,此时有两种情况:重新开始系统调用还是返回失败.

早期unix特征为,进程执行慢系统调用期间捕获信号时,该调用被中断并设置errno为EINTR。现代unix增加了sa_flags选项SA_RESTART可对单个信号要求自动恢复被中断的系统调用。

原则如下:如果进程阻塞于慢系统调用,并且进程捕获信号且该信号句柄返回,系统调用可能返回EINTR。 虽然有些unix能自动恢复系统调用,但是为了兼容性,我们必须准备慢系统调用返回EINTR,当检测到EINTR,要么重新开始系统调用,要么做其他处理。

Again:

       if (n=read(fd,buff, BUFSIZE) < 0) {

              if (errno ==EINTR)

                     goto Again;

              else

                     …}

分享到:
评论

相关推荐

    UNIX系统学习.rar

    6. **进程管理**:UNIX提供了丰富的进程控制命令,如`ps`(查看进程状态)、`kill`(发送信号到进程)、`nohup`(让程序在后台运行不受挂断影响)等。 7. **权限与用户管理**:UNIX的权限系统基于所有者、组和其他...

    Unix C学习指南

    在Unix环境中,还会涉及系统调用、信号处理等Unix特定的编程技术。不断地实践和阅读高质量的代码是提高编程能力的关键。同时,积极寻找和解决问题,以及参与开源项目,都能加速学习进程。 总之,Unix下的C语言学习...

    Unix的学习课件

    7. **进程管理**:Unix系统提供了丰富的进程控制命令,如`ps`(查看进程状态)、`kill`(发送信号给进程)、`nohup`(让进程在后台运行不受登录/注销影响)。 8. **网络和通信**:Unix系统在网络通信方面非常强大,...

    Unix傻瓜书,Unix学习经典数据

    《Unix傻瓜书》是一本面向初学者的经典Unix学习指南,旨在通过逐步引导的方式帮助读者深入理解Unix操作系统。这本书以浅显易懂的语言,详细介绍了Unix的基础知识、核心概念以及实用技巧,是学习Unix系统不可多得的...

    unix操作系统学习手册.rar

    《Unix操作系统学习手册》是一本全面且深入的指南,旨在帮助读者掌握Unix操作系统的配置与命令使用。Unix系统,作为一种历史悠久、广泛应用于服务器和科研领域的多用户、多任务操作系统,其强大而灵活的命令行界面和...

    unix学习教程

    《Unix学习教程》是一本旨在帮助读者快速掌握Unix操作系统编程的宝贵资料。Unix系统作为一款历史悠久、广泛应用的操作系统,其强大的稳定性和灵活性深受程序员和系统管理员喜爱。通过深入学习Unix,我们可以理解操作...

    UNIX基础学习知识

    **UNIX基础学习知识** 在IT领域,UNIX操作系统是一款历史悠久、广泛应用的多用户、多任务操作系统。它以其稳定、高效和可移植性著称,尤其在科研、工程和服务器管理等领域有着广泛的应用。本文将深入探讨UNIX的基础...

    Unix初學者使用手冊_Unix学习_

    接下来,你会学习到进程管理和调度,包括如何使用`ps`查看进程状态,`kill`发送信号终止进程,以及`nohup`让命令在后台持续运行。Unix的管道(pipe)和重定向功能是其强大的工具,可以组合命令并改变输入输出流,...

    unix学习资料,不错的

    3. **进程管理**: Unix提供了丰富的进程控制命令,如`ps`查看进程状态,`kill`发送信号终止进程,`nohup`让命令在后台运行不受登录退出影响。 4. **管道和重定向**: Unix的管道`|`可以将一个命令的输出作为另一个...

    unix_reader_writer.rar_linux reader writer_unix 信号_信号量_读写者_读写者问题

    通过分析这个项目,我们可以学习如何使用Unix的系统调用如`sem_init`, `sem_wait` (P操作), `sem_post` (V操作) 来实现信号量,并解决实际的同步问题。这对于理解和编写多线程或多进程应用程序,尤其是在涉及共享...

    unix程序员手册.zip_UNIX_unix程序员手册

    通过《UNIX程序员手册》,新手不仅可以学习到UNIX系统的基础知识,还能深入理解其设计哲学和工作原理,为后续的系统级编程和高级应用开发打下坚实基础。这本书不仅是入门工具,更是长期参考资料,值得反复研读和实践...

    UNIX操作系统学习资料

    本学习资料集旨在为初学者提供一个基础的UNIX学习平台,帮助你掌握基本的UNIX命令行操作,以及理解UNIX系统的运行机制。 1. **UNIX系统概述** - UNIX是最早采用分时系统设计的操作系统之一,由Ken Thompson和...

    Unix c学习笔记汇总.zip

    笔记可能涉及了Unix的文件系统结构、进程管理、I/O操作、信号处理、Shell脚本编写等内容。了解这些基础将帮助读者更好地理解和操作Unix环境。 2. **C语言基础**:C语言提供了低级别的内存管理和控制,使得开发者...

    Unix编程艺术/Unix环境高级编程(第二版)/Unix网络编程(第二版)

    作者详细讲解了Unix系统调用接口,包括文件I/O、进程控制、信号、内存映射等核心功能。此外,还涵盖了线程编程、进程间通信和POSIX标准等内容,对理解系统级编程提供了全面的指导。读者通过这本书可以深入了解Unix...

    Unix编程学习指南

    ### Unix编程学习指南 #### 一、概述 本指南旨在为初学者提供一套全面而系统的Unix编程学习路径,帮助读者迅速掌握Unix编程的核心概念和技术要点。通过本指南的学习,你可以了解Unix编程的基本流程,掌握关键的...

    UNIX学习资料 .

    本学习资料包包含了两份PDF文档:初级Unix 1.pdf和初级Unix 2.pdf,旨在帮助初学者入门UNIX系统。 1. **UNIX历史**:UNIX最初由Ken Thompson和Dennis Ritchie于1969年在AT&T贝尔实验室开发,它是一种分时操作系统,...

    unix学习笔记(网上转来的,和朋友们一起分享)

    这篇"Unix学习笔记"显然是为了帮助初学者掌握Unix的基础知识和操作技巧。 首先,让我们从"Chapter 1"开始,这通常会涵盖Unix的历史、基本概念以及安装。在这一章,你可以期待了解Unix是如何诞生的,它与Linux和类...

    Understanding Unix/Linux Programming

    书中的内容不仅涵盖了基础的系统调用、文件操作,还包括进程管理、网络编程等高级主题,是学习Unix/Linux系统编程的宝贵资料。光盘资源则为学习过程提供了丰富的实践练习,有助于巩固理论知识,提升实际操作技能。 ...

    unix c++ 学习资料 来自达内

    在深入探讨Unix与C++编程之前,我们先来理解一下这个学习资料的背景。这份资料来自达内,一个知名的IT培训机构,它强调了外企的师资、技术以及品质,这意味着培训内容将按照国际标准进行,适合对进入外企或者追求高...

    unix system programming in ocaml

    ### Unix系统编程与OCaml语言 #### 引言 本文档提供了一个关于Unix系统编程的入门课程...通过学习本教程,读者不仅可以掌握如何使用OCaml编写高效的Unix应用程序,还能了解到OCaml语言在系统编程领域中的优势和特点。

Global site tag (gtag.js) - Google Analytics