Linux信号编程实践(二) 信号发送函数和可重入函数

在早期的UNIX中信号是不可靠的,不可靠在这里指的是:信号可能丢失,一个信号发生了,但进程却可能一直不知道这一点。

现在Linux 在SIGRTMIN实时信号之前的都叫不可靠信号,这里的不可靠主要是不支持信号队列,就是当多个信号发生在进程中的时候(收到信号的速度超过进程处理的速度的时候),这些没来的及处理的信号就会被丢掉,仅仅留下一个信号。

可靠信号是多个信号发送到进程的时候(收到信号的速度超过进程处理信号的速度的时候),这些没来的及处理的信号就会排入进程的队列。等进程有机会来处理的时候,依次再处理,信号不丢失。

同时,信号的发送和安装也出现了新版本:信号发送函数sigqueue()及信号安装函数sigaction()。

sigaction和signal函数都是调用内核服务do_signal函数;[内核服务函数,应用程序无法调用该函数

非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。

关于信号发送的一些API:

1.kill

int kill(pid_t pid, int signo);

参数:pid:可能选择有以下四种

1. pid大于零时,pid是信号欲送往的进程的标识。2. pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。3. pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。4. pid小于-1时,信号将送往以-pid为组标识的进程。

sig:准备发送的信号代码,,假如其值为零则没有任何信号送出,但是系统会执行错误检查,通常会利用sig值为零来检验某个进程是否仍在执行。

返回值说明: 成功执行时,返回0。失败返回-1,errno被设为以下的某个值 EINVAL:指定的信号码无效(参数 sig 不合法) EPERM;权限不够无法传送信号给指定进程 ESRCH:参数 pid 所指定的进程或进程组不存在。

void handler(int sig){        printf("recvv a sig =%d\n",sig);}int main(){        if(signal(SIGUSR1,handler)==SIG_ERR)        ERR_EXIT("signal error!");        pid_t pid=fork();        if(pid==-1)                ERR_EXIT("fork error!");        else if(pid==0)        {//等于 killpg(getpgrp(),SIGUSR1);                pid=getpgrp();                kill(-pid,SIGUSR1);                /*                   kill(getppid(),SIGUSR1);                 *///以上                exit(EXIT_SUCCESS);        }        int n=5;        do{                n=sleep(n);        }while(n>0);//        return 0;}

注意点:

(1)sleep函数会被信号打断,进行完信号的处理函数后不再睡眠,而是继续执行sleep函数以后的操作。如果我们就是想要程序睡眠一段时间呢?通过man手册发现,sleep函数的返回值是 还剩余的秒数,所以可以采用循环的形式,即:

while(n=sleep(n));(2)如果发出信号的目标是进程组,那么子进程fork的时候会继承信号,从而会发生两次信号处理。

2.raise

raise()给自己发送信号,等价于raise(getpid(),sig)

3.killpg

4.sigqueue

int sigqueue(pid_t pid, int sig, const union sigval value); 给进程发送信号,支持排队,可以附带信息。5.alarm

alarm函数,设置一个闹钟延迟发送SIGALRM信号(告诉Linux内核n秒中以后,发送SIGALRM信号);但是alarm函数一次只能发送一个信号,所以必须递归调用才可以实现间歇性发送信号的功能。

void handler(int sig){        printf("recvv a sig =%d\n",sig);        alarm(1); //间接递归,持续发送信号}int main(){        if(signal(SIGALRM,handler)==SIG_ERR)        ERR_EXIT("signal error!");        alarm(1);        while(1)                pause();        return 0;}

可重入/不可重入函数一路走来,我们无法猜测将是迎接什么样的风景,

Linux信号编程实践(二) 信号发送函数和可重入函数

相关文章:

你感兴趣的文章:

标签云: