`

信号处理问题

阅读更多
注:本文摘自《深入理解计算机系统》第8章 --- 异常控制流。本文不适于不了解信号的人,在此也不对信号做过多解释,只是个人需要记录相关的信号处理问题而已,想了解更详细的请自行查阅相关资料。

程序只捕获一个信号时是简单直接的,但当要捕获多个信号时,就可能产生一些细微的问题。
1、待处理信号被阻塞。unix信号处理程序通常会阻塞当前处理程序正在处理的类型的待处理信号。比如,假设一个进程捕获了SIGCHLD信号(注:每个子进程终止或退出时,内核都会发送一个SIGCHLD信号给父进程),并且当前正在运行它的SIGCHLD处理程序,如果另一个 SIGCHLD 信号传递到这个进程,那么这个信号将变成待处理的,但不会被接收,直到处理程序返回。

2、待处理信号不会排队等待。任意类型至多只有一个待处理信号。因此,如果有两个类型为k的信号传送到一个目的进程,而由于目的进程当前正在执行信号k的处理程序,所以信号k是阻塞的,那么第二个信号就被简单地丢弃,它不会排队等待。关键思想是存在一个待处理的信号仅仅表明至少已经有一个信号到达了。

3、系统调用可以被中断。像read、wait 和 accpet 这样的系统调用潜在地会阻塞一段较长的时间,称为慢系统调用。在某些系统中,当处理程序捕获到一个信号时,被中断的慢速系统调用在信号处理程序返回时不再继续,而是立即返回给用户一个错误条件,并将error设置为EINTR。

我知道,要看懂这几句话可能不用例子只怕很难理解,所以想了下,还是把例子抄上来好些。
void handler1(int sig){
    pid_t pid;
    if((pid=waitpid(-1, NULL, 0)) < 0)
        unix_error("waitpid error");
    printf("Handler reaped child %d\n", (int)pid);
    Sleep(2);
    return;
}

int main(){
    int i, n;
    char buf[MAXBUF];
    if(signal(SIGCHLD, handler1) == SIG_ERR)
        unix_error("signal error");
    for(i=0; i<3; i++){
        if(Fork() == 0){
            printf("Hello from child %d\n", (int)getpid());
            Sleep(1);
            exit(0);
        }
    }
    if((n=read(SIGIN_FILENO, buf, sizeof(buf))) < 0)
        unix_error("read");
    printf("Parent processing input\n");
    while(1){
        ;
    }
    exit(0);
}

解释:父进程设置了一个SIGCHLD处理程序,然后创建了三个子进程,其中每个子进程运行1秒,然后终止。同时,父进程等待来自中端的一个输入行,随后处理它。这个处理被模型化为一个无限循环,当每个子进程终止时,内核通过发送一个SIGCHLD信号通知父进程,父进程捕获这个信号,回收一个子进程,做一些其它的清除工作,然后返回。
但当在linux上运行时,输出是类似这样的:
linux> ./signal1
Hello from child 10320
Hello from child 10321
Hello from child 10322
Handler reaped child 10320
Handler reaped child 10322
<cr>
Parent processing input

从中可看出,尽管发送了3个SIGCHLD信号给父进程,但是其中只有两个信号被接收了,因此父进程只是回收了两个子进程。此时若挂起父进程,用ps命令查看一下,可看到进程10321没有被回收,而是成为了一个僵尸进程。
为何会这样?尽管这个程序看似很正常,但其实它是有缺陷的,因为它无法处理信号阻塞、信号不排队等待和系统调用被中断这些情况。它实际发生的情况是:父进程接收并捕获了第一个信号,当处理程序还在处理第一个信号时,第二个信号就传送并添加到了待处理信号集合里。但因为信号SIGCHLD信号被SIGCHLD处理程序阻塞了,所以第二个信号就不会被接收。此后不久,就在处理程序还在处理第一个信号时,第三个信号到达了。因为已经有了一个待处理的SIGCHLD,所以第三个SIGCHLD信号会被丢弃。一段时间后,处理程序返回,内核注意到有一个待处理的SIGCHLD信号,就迫使父进程接收该信号。父进程捕获它,并第二次执行处理程序。在处理程序完成对第二个信号的处理后,已经没有待处理的SIGCHLD信号了,而且也绝不会再有,因为第三个SIGCHLD的所有信息都已经丢失了。所以教训是绝不可以用信号来对其它进程中发生的事件计数!

为了修正这个问题,必须想到存在一个待处理的信号只是暗示自进程最后一次收到一个信号以来,至少已经有一个这种类型的信号被发送了,所以必须修改SIGCHLD处理程序,使得每次SIGCHLD处理程序被调用时,回收尽可能多的僵尸子进程。在此只需修改SIGCHLD处理程序,其余的保持原样:
void handler2(int sig){
    pid_t pid;
    while((pid = waitpid(-1, NULL, 0)) > 0){
        printf("Handler reaped child %d\n", (int)pid);
    }
    if(error != ECHILD)
        unix_error("waitpid error");
    Sleep(2);
    return;
}

现在再次运行,结果就能回收所有僵尸子进程了,在此偷个懒就不贴运行结果了。
然而,革命尚未成功!本程序能够正确解决信号会阻塞和不会排队等待的情况,但它没有考虑系统调用被中断的可能性。在有些系统上,在从键盘上进行输入之前,被阻塞的read系统调用就提前返回一个错误:
solaris> ./signal2
Hello from child 18906
Hello from child 18907
Hello from child 18908
Handler reaped child 18906
Handler reaped child 18908
Handler reaped child 18907
read: Interrupted system call

出现这个问题是因为在特定的Solaris系统上,诸如read这样的慢速系统调用在被信号发送中断后,是不会自动重启的。相反,和linux系统自动重启被中断的系统调用不同,它们会提前返回给调用程序一个错误条件。修改时只要它能手动地重启被终止的read调用即可,本次需要修改主函数:
int main(){
    int i, n;
    char buf[MAXBUF];
    pid_t pid;

    if(signal(SIGCHLD, handler1) == SIG_ERR)
        unix_error("signal error");

    for(i=0; i<3; i++){
        if((pid=Fork()) == 0){
            printf("Hello from child %d\n", (int)getpid());
            Sleep(1);
            exit(0);
        }
    }
    whileda((n=read(SIGIN_FILENO, buf, sizeof(buf))) < 0){
        if(errno != EINTR)
            unix_error("read");
    }
    printf("Parent processing input\n");
    while(1){
        ;
    }
    exit(0);
}

分享到:
评论

相关推荐

    数字信号处理-时域离散随机信号处理答案(丁美玉)

    丁美玉的答案集可能涵盖了上述知识点的习题解答,通过解答这些题目,学习者能够加深对理论知识的理解,提升实际操作技能,并掌握如何将理论应用于实际的信号处理问题。这份资源对于学习和研究数字信号处理的学者来说...

    MATLAB信号处理.pdf

    MATLAB是一种广泛应用于科学计算、数据分析、算法开发和系统建模的高级编程环境。在信号处理领域,MATLAB因其强大的数学运算能力和丰富的...通过熟练掌握MATLAB的信号处理功能,用户能够高效地解决各种信号处理问题。

    北京邮电大学-数字信号处理-期末复习资料.pdf

    14. 实际应用中的数字信号处理问题:讨论在实际应用中遇到的数字信号处理问题和挑战,例如实现高效算法、数字信号处理器编程、实时信号处理等。 以上是数字信号处理领域的一些基础和高级知识点。为了更好地复习和...

    数字信号处理单片机及应用

    数字信号处理是电子信息技术中的一个核心领域,它涉及使用数字方法对信号进行分析、处理和...通过理解这些知识点,能够更好地把握数字信号处理的技术发展趋势,并在实际工作中有效地应用这些技术解决各种信号处理问题。

    现代数字信号处理(杨绿溪)课后习题答案

    例如,答案可能包含了解决特定信号处理问题的步骤,如如何使用离散傅立叶变换(DFT)来分析周期性信号,或者如何设计IIR滤波器实现特定频率响应。 在"现代数字信号处理"中,关键知识点包括: 1. **数字信号的基本...

    第三章(一)_优化阵列信号处理_

    压缩包中的eg3_1.m到eg3_6.m文件可能分别对应于不同的信号处理问题和算法实现,例如DOA估计、干扰对消、波束形成等。每个文件可能包含一个特定的优化问题的求解过程,比如使用特定的自适应算法解决实际问题。 7. *...

    阵列信号处理代码大全

    在IT领域,阵列信号处理是一门至关重要的技术,它主要应用于雷达、通信、声纳等领域,用于提高信号检测...通过深入学习和实践这些算法,你将能够处理更复杂的信号处理问题,提高系统性能,并为未来的创新打下坚实基础。

    数字信号处理_习题_北京交通大学

    1. 文件名包含"ans"的PDF文件,如dsp试题L1_01ans.pdf,很可能是对应练习题的答案解析,其中可能涵盖了解决数字信号处理问题的具体步骤、公式推导以及计算过程。 2. 文件名不包含"ans"的PDF文件,如dsp试题L1_01.pdf...

    《数字信号处理》答案

    习题可能要求计算这些统计量,理解它们的关系,并应用到实际信号处理问题中。 此外,书中可能还会涵盖其他主题,如多速率信号处理、数字信号的压缩与编码,以及现代数字信号处理的应用,如通信、图像处理和音频处理...

    统计信号处理与应用导论习题解答

    习题解答会帮助学生理解和应用这些复杂概念,解决实际的信号处理问题。 通过这些习题解答,学生不仅可以检验自己的学习成果,还能通过解题过程深化对统计信号处理原理的理解,提高解决实际问题的能力。对于每个习题...

    数字信号处理 习题答案

    《数字信号处理》是电子工程领域的一门重要课程,它主要研究如何在数字域内对信号进行分析、处理和变换...通过深入学习和解决这些习题,读者将能够熟练掌握数字信号处理的基础知识,并具备解决复杂信号处理问题的能力。

    张贤达书籍-《通信信号处理》《现代信号处理》《信号处理中的线性代数》《非平稳信号分析与处理》

    《信号处理中的线性代数》则是从矩阵和向量的角度探讨信号处理问题,线性代数是理解和解决多变量系统的基础,它在滤波器设计、特征提取和系统建模等领域具有重要作用。 最后,《非平稳信号分析与处理》聚焦于那些...

    统计信号处理习题答案 (Steven M.Kay 著 罗鹏飞 张文明等译)

    通过解决这些习题,学生能够提高分析问题和解决问题的能力,为将来在科研或工程实践中应对复杂信号处理问题打下坚实基础。 总之,《统计信号处理习题答案》是一本对于学习统计信号处理至关重要的资源,它不仅提供了...

    matlab.rar_MATLAB数字信号_matlab信号处理_信号处理_信号处理 matlab_数字信号处理

    4. 实例学习:"matlab数字信号处理实例.pdf"很可能包含了各种具体的信号处理问题的MATLAB代码实例,如滤波器设计、信号的频谱分析、噪声抑制、信号恢复等。通过这些实例,学习者可以理解如何在MATLAB环境中编写和...

    数字信号处理习题集

    【数字信号处理】是电子工程和通信领域的重要分支,主要涉及对数字形式的信号进行分析、变换、滤波和处理的技术。...通过实践,读者能够更好地掌握数字信号处理的核心概念,并应用于实际的信号处理问题中。

    数字信号处理MATLAB实验一

    在数字信号处理领域,MATLAB是一种广泛使用的工具,它提供了丰富的库函数和强大的计算能力,使得信号的分析、...通过不断实践和探索,我们可以利用MATLAB解决复杂的信号处理问题,例如噪声抑制、信号恢复、特征提取等。

    现代数字信号处理-3.pdf

    自适应滤波器的出现,主要是为了解决传统滤波器难以应对的非平稳信号处理问题。 自适应滤波器原理部分讨论了自适应滤波器的基本概念和工作原理。自适应滤波器的核心在于它的自适应能力,即滤波器的系数或参数能够...

    [数字信号处理教程] 程佩青 第三版 pdf

    《数字信号处理教程》程佩青第三版是深入学习数字信号处理领域的经典教材。...通过对压缩包内文件a301d80e05794b68b79b4d2e17e72879的阅读,读者可以更深入地理解和掌握这些概念,并应用到实际的信号处理问题中。

    随机信号分析与处理教材答案_答案_carefullypkz_随机信号分析与处理_

    该书主要针对电子工程、通信工程、计算机科学等领域的学生和研究人员,涵盖了随机变量、随机过程的基本概念,以及如何利用这些理论解决实际信号处理问题。这份答案集合可能是由carefullypkz整理,供学习者参考,以...

Global site tag (gtag.js) - Google Analytics