有关信号处理的程序解析

#用alarm函数发送信号

进程可以通过调用alarm函数向它自己发送SIGALRM信号

例子1:

#include "csapp.h"

int beeps = 0; //定义全局变量beeps并赋初值0,用于计数
 
/* SIGALRM handler */
void handler(int sig) { //信号处理程序handler,入口参数为整型的信号编号,无返回值
    sio_puts("BEEP\n"); //调用系统io函数sio_puts输出BEEP

    if (++beeps < 5)//++为前缀运算符,beeps先加1,后与5比较。这里共4次满足条件  
	alarm(1);//一秒钟之后,向调用进程发送SIGALRM信号 
    else { //第五次收到信号时
	sio_puts("BOOM!\n"); //调用系统io函数sio_puts输出BOOM
	_exit(0); //不清空输出缓冲区,直接退出,进程终止
    } 
} 

int main() { 
    signal(SIGALRM, handler);  //一旦接受到信号SIGALRM(来自alarm的定时器信号),就转而去执行handler程序
    alarm(1);//一秒钟之后,向调用进程发送SIGALRM信号
 
    while (1) { //进程不断执行while死循环(直到接收到SIGALRM信号)
	continue; //信号处理程序handler前四次返回此处
    } 
} 

该程序执行时,进程调用alarm函数向自己一共发送了5次SIGALRM信号,从而5次执行了信号处理程序handler,输出5次BEEP。最后一次调用handler函数时,因为计数条件限制,执行else语句,输出BOOM!,并退出调用进程。

程序运行结果如下:

#signal函数用于接收信号,并将控制转移到信号处理程序

sleep函数用于使调用进程休眠(从而让别的进程先执行),即将一个进程挂起一段指定的时间

这里关于typedef的使用参考了链接https://blog.csdn.net/davidsky11/article/details/28278973

#include <signal.h>

typedef void (*sighandler_t)(int);//将sighandler_t定义为一个指针类型(该指针用于指向返回值为void型,入口参数为int型的函数)

sighandler_t signal(int signum, sighandler_t handler);//入口参数signum为信号名称,handler为某个信号处理程序,若成功则返回前次处理程序的指针,若出错则为 SIG_ERR
#include <unistd.h>

unsigned int sleep(unsigned int secs);//入口参数secs为无符号整型,表示要求休眠的秒数;返回值为无符号整型,表示还要休眠的秒数

例子:

int ccount = 0;
void child_handler(int sig)//入口参数为信号编号,无返回值(该函数作用是回收终止的子进程,并输出相关提示信息)
{
    int child_status;//用于存储子进程退出状态
    pid_t pid = wait(&child_status);//回收终止的子进程,返回其pid,并将子进程退出状态存入child_status
    ccount--;//全局变量ccount减一,表示待回收的子进程数目减一
    printf("Received SIGCHLD signal %d for process %d\n", sig, pid); /* Unsafe *///输出收到来自哪个子进程的终止信号
    fflush(stdout); /* Unsafe *///清空输出缓冲区
}

/*
 * fork14 - Signal funkiness: Pending signals are not queued
 */
void fork14()
{
    pid_t pid[N];//定义pid数组用于在父进程中存储子进程的Pid
    int i;
    ccount = N;//将全局变量赋值为N(N==5)
    signal(SIGCHLD, child_handler);//一旦接收到子进程终止信号SIGCHLD,就转而执行信号处理程序child_handler

    for (i = 0; i < N; i++) {//循环5次,共创建5个子进程
	if ((pid[i] = fork()) == 0) {//父进程中,将子进程PID依次存入pid数组
	    sleep(1);//子进程休眠1s
	    exit(0);  /* Child: Exit *///子进程终止,并向父进程发送一个SIGCHLD信号
	}
    }
    while (ccount > 0)//直到子进程全部回收完,父进程才会跳出while循环
	;
}

本程序的sleep(1)使得子进程休眠了1s,这直接使得子进程最终只被回收了1个或2个(控制默认总是在父进程)。将源程序中sleep(1)删掉,或在while循环里调用sleep函数(使父进程休眠),可以看到回收多个子进程的情况。

运行结果:

删去源程序中的sleep(1),并在while循环里调用sleep(5)后的运行结果:

这里接收到信号的顺序是不确定的。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值