Linux 信号通信

信号的本质
软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。

收到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:

第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理。

第二种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。

第三种方法是,对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。

信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或者其它硬件故障);软件来源,最常用发送信号的系统函数是kill, sigqueue函数,软件来源还包括一些非法运算等操作。

信号API
安装信号 (signal 和sigaction函数)
void signal (int signum, void (*handler))(int)))(int);
signal 无法携带信息,有点类似于system函数,去执行一个动作。
第一个参数指定信号的值,第二个参数指定针对前面信号值的处理,可以忽略该信号(参数设为SIG_IGN)但SIGKILL 和SIGSTOP无法忽略;可以采用系统默认方式处理信号(参数设为SIG_DFL);也可以自己实现处理方式(参数指定一个函数地址)。
当第二个参数是处理函数时,处理函数格式如下
void handler (int signum)
{

}

#include <signal.h>
#include<stdio.h>

      // typedef void (*sighandler_t)(int);

      // sighandler_t signal(int signum, sighandler_t handler);

        void handler(int signum)
        {
                switch(signum)
                {
                        case 2 :
                                printf("quilt\n");
                                break;
                        case 9 :
                                printf("kill\n");
                                break;
                        case 19 :
                                printf("stop\n");
                                break;
                }
                printf("never quilt\n");
        }

int main()
{
        signal(SIGINT,handler);
        signal(SIGKILL,handler);
        signal(SIGSTOP,handler);
        while(1);
        return 0;
}

int sigaction(int signum,const struct sigaction *act,struct sigaction oldact));
可携带信息
sigaction函数用于改变进程接收到特定信号后的行为。该函数的第一个参数为信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)。第二个参数是指向结构sigaction的一个实例的指针,在结构sigaction的实例中,指定了对特定信号的处理,可以为空,进程会以缺省方式对信号处理;第三个参数oldact指向的对象用来保存返回的原来对相应信号的处理,可指定oldact为NULL。如果把第二、第三个参数都设为NULL,那么该函数可用于检查信号的有效性。
第二个参数
struct sigaction{
void () (int ) handler;
sigset_t sa_mask;
int sa_flags;
}
结构体的两个元素_sa_handler以及
_sa_sigaction指定信号关联函数,即用户指定的信号处理函数。除了可以是用户自定义的处理函数外,还可以为SIG_DFL(采用缺省的处理方式),也可以为SIG_IGN(忽略信号)。
处理函数
void handler(int signum,siginfo_t *info,void *context)
{

}

#include<stdio.h>
#include<signal.h>

void handler(int signum,siginfo_t *info,void *context)
{
        printf("get signum=%d\n",signum);
        if(context!=NULL)
        {
                printf("get data=%d\n",info->si_int);
                printf("get data=%d\n",info->si_value.sival_int);
                printf("from%d\n",info->si_pid);

        }


}


int main()
{
        struct sigaction act ;
        act.sa_sigaction=handler;
        act.sa_flags=SA_SIGINFO;// can get message
        printf("pid=%d\n",getpid());
        sigaction(SIGUSR1,&act,NULL);
        while(1);
        return 0;

信号发送函数
int kill(pid_t pid,int signo);
该系统调用可以用来向任何进程或进程组发送任何信号。参数pid的值为信号的接收进程

pid>0 进程ID为pid的进程

pid=0 同一个进程组的进程

pid<0 pid!=-1 进程组ID为 -pid的所有进程

pid=-1 除发送进程自身外,所有进程ID大于1的进程
Signo是信号值。

#include <signal.h>
#include<stdio.h>

      // typedef void (*sighandler_t)(int);

      // sighandler_t signal(int signum, sighandler_t handler);


int main(int argc ,char **argv)
{

        int signum=atoi(argv[1]);
        int pid=atoi(argv[2]);
        printf("signum=%d\n",signum);
        printf("pid=%d\n",pid);
        kill(pid,signum);
        printf("send signal ok\n");
        return 0;
}

int sigqueue(pid_t pid, int sig, const union sigval val)
sigqueue的第一个参数是指定接收信号的进程ID,第二个参数确定即将发送的信号,第三个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值。

typedef union sigval {

           int  sival_int;

           void *sival_ptr;

}sigval_t;
sigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。

在调用sigqueue时,sigval_t指定的信息会拷贝到对应sig 注册的3参数信号处理函数的siginfo_t结构中,这样信号处理函数就可以处理这些信息了。由于sigqueue系统调用支持发送带参数信号,所以比kill()系统调用的功能要灵活和强大得多。

#include<stdio.h>
#include<signal.h>
int main(int argc ,char **argv )
{
        int signum;
        int pid;
        signum=atoi(argv[1]);
        pid=atoi(argv[2]);
        union sigval value;
        value.sival_int=100;
        sigqueue(pid,signum,value);
        printf("%d,done\n",getpid());

        return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值