20191227甘泞与第六章学习笔记

技术20191227甘泞与第六章学习笔记 20191227甘泞与第六章学习笔记第6章 信号和信号处理
6.1信号和中断
信号:发给进程的请求,将进程从正常执行转移到中断处理。
中断:是从I/O设备或协处

20191227甘宁第六章学习笔记

第6章 信号和信号处理

6.1信号和中断

信号:发送给进程的请求,将进程从正常执行转移到中断处理。

中断:从输入输出设备或协处理器发送到中央处理器的外部请求,将中央处理器从正常执行转移到中断处理。

“中断”是发送给进程的事件,它将进程从正常活动转移到其他活动,称为“中断处理”。“进程”在完成“中断”处理后可以恢复正常活动。

有以下类型的终端:

1.人员中断

2.过程中断

3.硬件中断

4.进程的陷阱错误

Unix/Linux的信号处理

(1)按Ctrl C通常会导致当前正在运行的进程终止。原因如下:Ctrl C组合键会产生键盘硬件中断。键盘中断处理程序将Ctrl C组合键转换为SIGINT(2)信号,发送给终端上的所有进程,唤醒等待键盘输入的进程。在内核模式下,每个进程都必须检查和处理未完成的信号。对于大多数信号,进程的默认操作是调用内核的kexit(exitValue)函数来终止。在Linux中,exitValue的低位字节是导致进程终止的信号号。

(2)用户可以使用命令nohup a.out在后台运行程序。即使在用户退出后,该进程也将继续运行。

(3)用户再次登录时可能会发现(通过ps-u LTD)后台进程仍在运行。用户可以使用sh命令kill pid(或kill -s 9 pid)来终止进程。

信号处理函数

每个处理模块都有一个信号处理阵列intsig [32]。sig[32]数组的每个条目指定如何处理相应的信号,其中0表示DEFault,1表示IGNore。下图显示了信号位向量、屏蔽位向量和信号处理功能。

如果信号位向量中的位I为1,将生成信号I或将其发送给进程。如果屏蔽位向量的位1为1,信号将被阻塞或屏蔽。否则,信号不会被阻断。只有当信号存在且未被阻塞时,信号才会生效或被传递给进程。

信号的发送

发送信号的主要功能有kill()、raise()、sigqueue()、alarm()、setitimer()和abort()。1、kill()

#包含系统/类型. h

#包含信号. h

int kill(pid_t pid,int signo)

参数pid值信号的接收过程

0 pid进程id为pid进程。

Pid=0同一进程组的进程

pid0 pid!=-1进程组标识为-pid的所有进程

Pid=-1进程标识大于1的所有进程,发送进程本身除外

Sinno是信号值。当它为0(即零信号)时,它实际上不发送任何信号,但照常进行错误检查。因此,它可以用来检查目标进程是否存在,以及当前进程是否有向目标发送信号的权限(具有root权限的进程可以向任何进程发送信号,而没有root权限的进程只能向属于同一会话或同一用户的进程发送信号)。

Kill()最常用于pid0被调用时的信令,调用成功返回0;否则,返回-1。注意:在pid0的情况下,不同的版本对于哪些进程会接收信号有不同的看法,其实很简单。只需参考内核源代码/signal.c .上表中的规则参考红帽7.2。

2、raise()

#包含信号. h

int raise(int signo)

向进程本身发送信号,参数是要发送的信号值。呼叫成功返回0;否则,返回-1。

3、sigqueue()

#包含系统/类型. h

#包含信号. h

int sigqueue(pid_t pid,int sig,const union sigval)

呼叫成功返回0;否则,返回-1。

Sigqueue()是一个比较新的信令系统调用,主要是针对实时信号提出的(当然也支持前32种)。支持信号有参数,与函数sigaction()一起使用。

sigqueue的第一个参数指定了接收信号的进程ID,第二个参数决定了要发送的信号,第三个参数是联合数据结构union sigval,它指定了信号传输的参数,也就是俗称的4字节值。

typedef union sigval { int sival _ int;void * sival _ ptr} sigval _ t;

Sigqueue()提供的附加信息比kill()多,但是sigqueue()只能向一个进程发送信号,而不能向一个进程组发送信号。如果signo=0,它将被执行。

错误检查,但实际上不发送任何信号,0值信号可用于检查pid的有效性以及当前进程是否有权限向目标进程发送信号。

在调用sigqueue时,sigval_t指定的信息会拷贝到3参数信号处理函数(3参数信号处理函数指的是信号处理函数由sigaction安装,并设定了sa_sigaction指针,稍后将阐述)的siginfo_t结构中,这样信号处理函数就可以处理这些信息了。由于sigqueue系统调用支持发送带参数信号,所以比kill()系统调用的功能要灵活和强大得多。

注:sigqueue()发送非实时信号时,第三个参数包含的信息仍然能够传递给信号处理函数; sigqueue()发送非实时信号时,仍然不支持排队,即在信号处理函数执行过程中到来的所有相同信号,都被合并为一个信号。

4、alarm()

#include unistd.h 
unsigned int alarm(unsigned int seconds) 

专门为SIGALRM信号而设,在指定的时间seconds秒后,将向进程本身发送SIGALRM信号,又称为闹钟时间。进程调用alarm后,任何以前的alarm()调用都将无效。如果参数seconds为零,那么进程内将不再包含任何闹钟时间。
返回值,如果调用alarm()前,进程中已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。

5、setitimer()

#include sys/time.h 
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)); 

setitimer()比alarm功能强大,支持3种类型的定时器:

ITIMER_REAL: 设定绝对时间;经过指定的时间后,内核将发送SIGALRM信号给本进程;
ITIMER_VIRTUAL 设定程序执行时间;经过指定的时间后,内核将发送SIGVTALRM信号给本进程;
ITIMER_PROF 设定进程执行以及内核因本进程而消耗的时间和,经过指定的时间后,内核将发送ITIMER_VIRTUAL信号给本进程;
Setitimer()第一个参数which指定定时器类型(上面三种之一);第二个参数是结构itimerval的一个实例,结构itimerval形式见附录1。第三个参数可不做处理。

Setitimer()调用成功返回0,否则返回-1。

6、abort()

#include stdlib.h 
void abort(void);

向进程发送SIGABORT信号,默认情况下进程会异常退出,当然可定义自己的信号处理函数。即使SIGABORT被进程设置为阻塞信号,调用abort()后,SIGABORT仍然能被进程接收。该函数无返回值。

信号捕捉函数

进程可使用系统调用:int r =signal(int signal_numberr void *handler);来修改选定信号编号的处理函数,SIGKILL(19)除外,它们不能修改。signal()系统调用在所有类Unix系统中均可用,但它有一些缺点:

  • 在执行已安装的信号捕捉函数之前,通常将信号处理函数重置为DEFault。为捕捉下一次出现相同的信号,必须重新安装捕捉函数。
  • signal()不能阻塞其他信号
  • 不同Unix版本的signal。可能会有所不通不同。
    所以现在signal()已经被sigaciton()所代替,它的原型是int sigaction (int signum, const struct sigaction *act, struct sigaction *oldact);,sigaction结构体的定义为

其中重要的字段如下:

sa_handler :该字段是指向处理函数的指针,该函数与signal()的处理函数有相同的原型。
sa_sigaction:该字段是运行信号处理函数的另一种方法。它的信号编号旁边有两个额外参数,其中siginfo t *提供关于所接收信号的更多信息。
sa_mask:可在处理函数执行期间设置要阻塞的信号。
sa_flags :可修改信号处理进程的行为。若要使用sa_sigaction处理函数,必须将sa_flags设置为SA_SIGINFO。

实践内容

/* sigset.c */
    #include sys/types.h
    #include unistd.h
    #include signal.h
    #include stdio.h
    #include stdlib.h
    /* 自定义的信号处理函数 */
    void my_func(int signum)
    {
        printf("If you want to quit,please try SIGQUIT\n");
    }
    int main()
    {
        sigset_t set,pendset;
        struct sigaction action1,action2;
        /* 初始化信号集为空 */
        if (sigemptyset(set)  0)
        {
            perror("sigemptyset");
            exit(1);
        }
        /* 将相应的信号加入信号集 */
        if (sigaddset(set, SIGQUIT)  0)
        {
            perror("sigaddset");
            exit(1);
        }
        if (sigaddset(set, SIGINT)  0)
        {
            perror("sigaddset");
            exit(1);
        }
        if (sigismember(set, SIGINT))
        {
            sigemptyset(action1.sa_mask);
            action1.sa_handler = my_func;
            action1.sa_flags = 0;
            sigaction(SIGINT, action1, NULL);
        }
        if (sigismember(set, SIGQUIT))
        {
            sigemptyset(action2.sa_mask);
            action2.sa_handler = SIG_DFL;
            action2.sa_flags = 0;
            sigaction(SIGQUIT, action2,NULL);
        }
        /* 设置信号集屏蔽字,此时set中的信号不会被传递给进程,暂时进入待处理状态 */
        if (sigprocmask(SIG_BLOCK, set, NULL)  0)
        {
            perror("sigprocmask");
            exit(1);
        }
        else
        {
            printf("Signal set was blocked, Press any key!");
            getchar();
        }
        /* 在信号屏蔽字中删除set中的信号 */
        if (sigprocmask(SIG_UNBLOCK, set, NULL)  0)
        {
            perror("sigprocmask");
            exit(1);
        }
        else
        {
            printf("Signal set is in unblock state\n");
        }
        while(1);
        exit(0);
    }

该程序的运行结果如下,可以看见,在信号处于阻塞状态时,所发出的信号对进程不起作用,并且该信号进入待处理状态。读者按任意键,并且信号脱离了阻塞状态后,用户发出的信号才能正常运行。这里SIGINT已按照用户自定义的函数运行,请读者注意阻塞状态下SIGINT的处理和非阻塞状态下SIGINT的处理有何不同。

问题与解决

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/89921.html

(0)

相关推荐

  • 大于小于号怎么用,一年级数学的大于号小于号怎么分

    技术大于小于号怎么用,一年级数学的大于号小于号怎么分大于号小于号的区分方法:尖角向左的是小于号,尖角向右的是大于号大于小于号怎么用。 1、大于号、小于号被广泛运用在算数中,是小学必学的内容。是数学中不等式运算符号的一种。

    生活 2021年10月25日
  • 怎么做一个Excel动态图表

    技术怎么做一个Excel动态图表本篇文章给大家分享的是有关怎么做一个Excel动态图表,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。 本文说明下图是一个比较

    攻略 2021年10月21日
  • Python中字符串连接效率最高的方式是什么

    技术Python中字符串连接效率最高的方式是什么本篇内容介绍了“Python中字符串连接效率最高的方式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧

    攻略 2021年11月29日
  • 古典密码学——移位密码 Shift Cipher

    技术古典密码学——移位密码 Shift Cipher 古典密码学——移位密码 Shift Cipher移位密码的理论基础是数论中的模运算。模运算的基本定义:假设a和b均为整数,m是一正整数。若m整除a-

    礼包 2021年12月3日
  • HBase协处理器加载的方式有哪些

    技术HBase协处理器加载的方式有哪些这篇文章主要介绍“HBase协处理器加载的方式有哪些”,在日常操作中,相信很多人在HBase协处理器加载的方式有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望

    攻略 2021年12月9日
  • 会意字大全,象形、指事、会意、形声字各二十个

    技术会意字大全,象形、指事、会意、形声字各二十个象形字:雨会意字大全、元、木、眉、左、右、门、龟、车、月、龟、马、鱼、日、门、木、山、手、羊、草、鸟、虫、川、耳、口、人、田、水、火 指事字:上、一、二、下、丨、丩、爻、元

    2021年10月21日