`
oolala
  • 浏览: 102964 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
09c341db-7f05-3f2b-a572-9ee69a5d8a77
unix环境高级编程
浏览量:22636
社区版块
存档分类
最新评论

Unix环境高级编程笔记:10、信号

阅读更多
信号是软件中断,信号提供了一种处理异步事件的方法。
1、信号概念
    每个信号都有一个名字,这些名字都以三个字符SIG开头。
    SIGABRT是夭折信号,当进程调用abort函数时产生这种信号
    SIGALRM是闹钟信号,当由alarm函数设置的计时器超时后产生此信号。
 
    在头<signal.h>中,这些信号都被定义为正整数(信号编号).
 
    很多条件可以产生信号 :
    a)当用户按某些终端键时,引发终端产生信号
        ctrl+c产生中断信号(SIGINT)
    b)硬件异常产生信号:除数为0、无效内存引用
        对执行一个无效内存引用的进程产生SIGSEGV
    c)进程调用kill(2)函数可将信号发送给另一个进程或进程组
    d)kill(1)命令将信号发送给其他进程
    e)当检测到某种软件条件已经发生,并应将其通知有关进程时也产生信号。
 
    信号是异步事件,产生信号的事件对进程而言是随机出现的。进程不能简单的测试一个变量来判断是否出现一个信号,而是必须告诉内核
    “在此信号出现时,请执行下列操作。”
 
    可以要求内核在某个信号出现时按照下列三种方式之一进行处理,我们称之为信号的处理
    (1)忽略此信号
        二种信号决不能被忽略:SIGKILL SIGSTOP
    (2)捕捉信号
    (3)执行系统默认动作
        每一种信号的默认动作。注,针对大多数信号的系统默认动作是终止进程。
 
    
    在“默认动作”列中,“终止+core”表示在进程当前工作目录的core文件中复制该进程的存储映象
 

2、signal
    #include <signal.h>
    void (*signal(int signo,void (*func)(int))) (int);
    
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
static void sig_usr(int signo);
 
int main(int argc, char **argv) {
if(signal(SIGUSR1,sig_usr) == SIG_ERR)
printf("signal error");
if(signal(SIGUSR2,sig_usr) == SIG_ERR)
printf("signal error");
 
for(;;) {
pause();
}
}
 
static void sig_usr(int signo) {
if(signo == SIGUSR1) {
printf("recived sigusr1");
}
if(signo == SIGUSR2) {
printf("recived sigusr2");
}
printf("recived %d",signo);
}
 
 
kill -SIGUSR1 11251
kill -SIGUSR2 11251
 
程序启动:
1)当执行一个程序时,所有信号的状态都是系统默认或忽略,通常所有信号都被设置为它们的默认动作,除非调用exec的进程忽略该信号。
    
     一个具体的例子是一个交互式shell如何处理针对后台进程的中断和退出信号
    cc main.c &
    shell自动将后台进程对中断和退出信号的处理方式设置为忽略。于是按中断键时不会影响到后台进程。
 
    很多捕捉这二个信号的交互式程序具有下列形式的代码 :
    void sig_int(int),sig_quit(int);
    
    if(signal(SIGINT,SIG_IGN) != SIG_IGN)
        signal(SIGINT,sig_int);
    if(signal(SIGQUIT,SIG_IGN) != SIG_IGN)
        signal(SIGQUIT,sig_quit);
 
2)进程创建
    当一个进程调用fork时,其子进程继承父进程的信号处理方式。因为子进程在开始时复制了父进程的存储映像,所以信号捕捉函数的地址在子进程中是有意义
 
 

3、可重入函数
    进程捕捉到信号并对其进行处理时,进程正在执行的指令序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。
如果从信号处理程序返回,则继续执行在捕捉到信号时进程正执行的正常指令序列。
 
若信号处理程序中调用一个不可重入函数,则其结果是不可预见的。
 

4、可靠信号术语
    1)当引发信号的事件发生时,为进程产生一个信号。可件可以是硬件异常、软件条件(alarm计时器超时)、终端产生的信号或调用kill。
    2)当对信号采取了这种动作时,我们说向进程递送了一个信号。
    3)在信号产生(generation)和递送(delivery)之间的时间间隔内,称信号是未决的(pending)
    4)进程可以选用信号递送阻塞
    5)进程调用sigpending判断哪些信号是设置为阻塞并处于未决状态
    6)每个进程都有一个信号屏蔽字(signal mask),它规定了当前要阻塞递送到该进程的信号集。
    7)sigset_t,保存一个信号集,信号屏蔽字就存放在这些信号集中
 
 

5、kill raise
kill函数将信号发送给进程或进程组。raise函数则允许进程向自身发送信号
#include <signal.h>
int kill(pid_t pid,int signo);
int raise(int signo);
 
raise(signo) 等价于kill(getpid(),signo);
 
pid>0    将该信号发送给进程ID为pid的进程
pid==0 将该信号发送给与发送进程属于同一进程组的所有进程
pid<0    将该信号发送给其进程组ID等于pid的绝对值,而且发送进程具有向其发送信号的权限。
pid==-1将该信号发送给发送进程有权限向它们发送信号的系统上的所有进程。
 

6、alarm和pause
    使用alarm函数可以设置一个计时器,在将来某个指定的时间该计时器会超时。当计时器超时时,产生SIGALRM信号。
    如果不忽略或不捕捉此信号,则其默认动作是终止调用该alarm函数的进程。
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
参数seconds的值是秒数,经过了指定的seconds秒后产生信号SIGALRM。
    
pause函数使调用进程挂起直至捕捉到一个信号。
#incude <unistd.h>
int pause(void);
 
7、信号集
    我们需要有一个能表示多个信号---信号集(signal set)的数据类型。
    sigset_t表示一个信号集
    
#include <signal.h>
int sigemptyset(sigset_t *set);         //初始化由set指向的信号集,清除其中所有信号            
int sigfillset(sigset_t *set);               //初始化由set指向的信号集,使其包括所有信号 
int sigaddset(sigset_t *set,int signo);
int sigdelset(sigset_t *set,int signo);
        

8、sigprocmask函数
    sigprocmask可以检测或更改其信号屏蔽字,或者在一个步骤中同时执行这二个操作。
    
#include <signal.h>
int sigprocmask(int how,const sigset_t *restrict set,siset_t #restrict oset);
 
9、sigpending
    sigpending函数返回信号集,其中的各个信号对于调用进程是阻塞的而不能递送,因而也一定是当前未决的。
#include <signal.h>
int sigpending(sigset_t *set);
 
10、sigaction
    sigaction函数的功能是检查或修改与指定信号相关的处理动作。 
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);
 
11、sigsetjmp   siglongjmp
    用于非局部转移的setjmp和longjmp,在信号处理程序中经常调用longjmp函数以返回到程序的主循环中,而不是从该处理程序返回。
 
    调用longjmp有一个问题,当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被自动地加到进程的信号屏蔽字中。
这阻止了后来产生的这种信号中断该信号处理程序。
    
       #include <setjmp.h>
 
       int sigsetjmp(sigjmp_buf env, int savesigs);
       void siglongjmp(sigjmp_buf env, int val);
    如果savemask非0,则sigsetjmp在env中保存进程的当前信号屏蔽字。
    调用setlongjmp时,如果带非0 savemask的sigsetjmp调用已经保存了env,则siglongjmp从其中恢复保存的信号屏蔽字。
 
12、sigsuspend
 
13、abort
 
14、system
 
15、sleep
 

 

分享到:
评论

相关推荐

    UNIX环境高级编程 笔记

    ### UNIX环境高级编程知识点 #### 一、UNIX系统基础与用户信息管理 - **系统目录结构**:UNIX系统采用层次化的目录结构来组织文件。其中,`/etc/passwd` 文件存储了用户的登录信息,包括用户名、用户ID、加密密码...

    UNIX环境高级编程第二版(高清电子书)

    《UNIX环境高级编程第二版》是一本深入探讨UNIX操作系统下高级编程技术的专著,尤其适合于对UNIX系统有深入了解需求的程序员、系统管理员以及计算机科学领域的学生和研究人员。本书的高清电子书版本,提供了清晰的...

    APUE读书笔记(Unix高级环境编程)

    - **Unix手册页**:介绍如何使用`man`命令查询Unix/Linux系统中的命令、函数等的文档,是学习Unix编程的重要资料来源。 - **系统调用与库函数**:系统调用是应用程序与操作系统内核之间的接口,库函数则是对系统调用...

    UNIX系统编程学习笔记

    在进入UNIX系统编程的学习之前,我们首先需要理解UNIX的基本概念。UNIX是一种多用户、多任务的操作系统,由贝尔实验室在1960年代末开发。它以其简洁、强大的命令行接口和丰富的工具集而闻名,是许多现代操作系统设计...

    Unix-Linux编程实践教程

    1. **shell编程**:讲解Bash shell和其他Unix shell的基本语法,包括命令行参数、环境变量、重定向、管道和脚本编写等。 2. **进程管理**:介绍进程创建(fork和exec)和进程通信(管道、套接字、信号、共享内存、...

    学习《高级Linux环境编程》读书笔记(APUE读书笔记)

    《高级Linux环境编程》或称为APUE(Advanced Programming in the UNIX Environment),是一本由W. Richard Stevens和Stephen A. Rago合著的关于UNIX环境编程的经典书籍。这本书详细介绍了UNIX系统编程的高级特性,...

    LINUX与UNIX SHELL编程指南 读书笔记

    在深入探讨《LINUX与UNIX SHELL编程指南》的读书笔记之前,让我们首先理解Linux和Unix Shell编程的基础概念。Linux是一种自由开源的操作系统,它的内核由林纳斯·托瓦兹开发,而Unix则是一个历史悠久的多用户、多...

    《LINUX与UNIX SHELL编程指南》读书笔记

    读书笔记可能还涵盖了错误处理、调试技巧、最佳实践和一些高级特性,如进程控制、信号处理、陷阱(trap)命令,以及如何使用awk和sed等强大的文本处理工具。 通过阅读这份笔记,你可以深入了解Linux和Unix Shell...

    电子科技大学Unix复习资料自己整理

    Unix系统主要由内核、shell、工具和应用程序四部分组成,提供了高效、灵活的工作环境。 二、Unix shell Unix shell是用户与操作系统交互的接口,常见的有Bash(Bourne Again SHell)。通过shell,用户可以执行命令...

    unix 笔记

    Unix以其简洁的命令行界面、强大的文本处理工具和强大的编程环境而闻名,是许多现代操作系统(如Linux和Apple的macOS)的基础。 Unix的核心组件包括内核、shell、文件系统和一组称为“Unix工具”的小型实用程序。...

    达内课程 unix系统下c语言课程

    3. C语言高级概念:包括指针、结构体、联合体、枚举、文件操作等,这些都是C语言的核心特性,特别是在Unix系统中,熟练掌握这些内容能让你更好地进行系统级编程。 4. Unix系统调用:Unix提供了丰富的系统调用接口,...

    qt 学习笔记 qt学习笔记

    ### Qt学习笔记知识点详解 #### 一、从Hello Qt开始 **知识点1:Qt程序的基本结构** - **头文件引入**: - 第1行和第2行代码中,`#include &lt;QApplication&gt;` 和 `#include &lt;QLabel&gt;` 是引入Qt中的两个类:`...

    UNIX多线程学习笔记

    【UNIX多线程学习笔记】 在UNIX操作系统中,多线程是一种重要的编程模型,它允许多个执行流在单个进程中并发运行。多线程带来了许多优势,包括提高应用程序响应速度,充分利用多CPU系统的资源,以及优化程序结构,...

    linux 系统编程 尚观 linux内核驱动开发 笔记

    Linux是一种自由、开放源码的类Unix操作系统,广泛应用于服务器、桌面环境以及各种嵌入式设备。它的核心部分是内核,负责管理硬件资源、调度进程、管理内存等核心功能。 系统编程是指直接与操作系统交互的程序编写...

    linux编程学习笔记PDF资料下载.txt

    ### Linux高级编程技术 #### 7. 内存管理 - **内存分配**:Linux提供了多种方式来分配内存,如malloc()、calloc()、realloc()、free()等函数。 - **共享内存**:多个进程之间可以通过共享内存段的方式实现通信。 - ...

    《LINUX与UNIX SHELL编程指南》

    《LINUX与UNIX SHELL编程指南》是一本深入讲解Linux和UNIX Shell编程的书籍,适合对操作系统有浓厚兴趣,特别是热衷于Linux环境下的命令行交互和自动化脚本编程的爱好者阅读。本书全面覆盖了Shell的基础知识、高级...

Global site tag (gtag.js) - Google Analytics