Linux开发——Signal异步通知机制

目录

 

目标:

实战:

Linux中的信号

信号的基本操作

相关函数

信号集合操作

未决信号


目标:

           如何发起异步操作(对本身发起,对其他进程发起)

          如何安装信号

          如何屏蔽和管理信息

          如何利用信号进行阻塞操作

实战:

          信号驱动的服务器

          电报机

Linux中的信号

信号      取值          默认动作   含义(发出信号的原因)
SIGHUP      1           Term    终端的挂断或进程死亡
SIGINT      2           Term    来自键盘的中断信号
SIGQUIT     3           Core    来自键盘的离开信号
SIGILL      4           Core    非法指令
SIGABRT     6           Core    来自abort的异常信号
SIGFPE      8           Core    浮点例外
SIGKILL     9           Term    杀死
SIGSEGV     11          Core    段非法错误(内存引用无效)
SIGPIPE     13          Term    管道损坏:向一个没有读进程的管道写数据
SIGALRM     14          Term    来自alarm的计时器到时信号
SIGTERM     15          Term    终止
SIGUSR1     30,10,16    Term    用户自定义信号1
SIGUSR2     31,12,17    Term    用户自定义信号2
SIGCHLD     20,17,18    Ign     子进程停止或终止
SIGCONT     19,18,25    Cont    如果停止,继续执行
SIGSTOP     17,19,23    Stop    非来自终端的停止信号
SIGTSTP     18,20,24    Stop    来自终端的停止信号
SIGTTIN     21,21,26    Stop    后台进程读终端
SIGTTOU     22,22,27    Stop    后台进程写终端
             
SIGBUS      10,7,10     Core    总线错误(内存访问错误)
SIGPOLL                 Term    Pollable事件发生(Sys V),与SIGIO同义
SIGPROF     27,27,29    Term    统计分布图用计时器到时
SIGSYS      12,-,12     Core    非法系统调用(SVr4)
SIGTRAP     5           Core    跟踪/断点自陷
SIGURG      16,23,21    Ign     socket紧急信号(4.2BSD)
SIGVTALRM   26,26,28    Term    虚拟计时器到时(4.2BSD)
SIGXCPU     24,24,30    Core    超过CPU时限(4.2BSD)
SIGXFSZ     25,25,31    Core    超过文件长度限制(4.2BSD)
             
SIGIOT      6           Core    IOT自陷,与SIGABRT同义
SIGEMT      7,-,7       Term
SIGSTKFLT   -,16,-      Term    协处理器堆栈错误(不使用)
SIGIO       23,29,22    Term    描述符上可以进行I/O操作
SIGCLD      -,-,18      Ign     与SIGCHLD同义
SIGPWR      29,30,19    Term    电力故障(System V)
SIGINFO     29,-,-              与SIGPWR同义
SIGLOST     -,-,-       Term    文件锁丢失
SIGWINCH    28,28,20    Ign     窗口大小改变(4.3BSD, Sun)
SIGUNUSED   -,31,-      Term    未使用信号(will be SIGSYS)

信号的基本操作

        发送信号    kill -x pid      函数:int kill(pid,signum)

        捕获信号   signal(signum,函数)== SIG_ERR

        忽略信号   signal(signum,SIG_IGN)

相关函数

         pause()使调用进程(或线程)进入休眠状态,直到传递的信号终止进程或导致调用信号捕获函数。

         alarm(4)定时器,4s后返回  重复使用会让上一个定时器返回,返回内容是剩余时间 发送SIGALRM信号

         ualarm(5000000,2000000) 第一5s返回  之后2s返回一次   发送SIGALRM信号(注:该函数多次实验,均未成功)

         int getitimer(int which,struct itimerval * curr_value);

         int setitimer(int which,const struct itimerval * new_value,struct itimerval(old_value);

                    ITIMER_REAL    根据系统时间递减

                    ITIMER_VIRTUAL   根据程序执行时间递减

                    ITIMER_PROG    进程执行,系统调用的时候才递减

                     struct itimerval 

                                        {struct itmerval it_interval   //间隔值

                                         struct itmerval in_value //第一次值}

                     struct itmerval 

                                       {time_t   tv_sec;                  s单位

                                        suseconds_t  tv_usec ;           mincroseconds 微秒为单位}

          int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);

                     struct sigaction 

                                   void (*sa_handler)(int)         和参数2    二选一

                                    void (*sa_sigaction)(int ,siginfo_t *,void *);

                                   sigset_t  sa_mask;     信号屏蔽集合

                                   //清空信号sigemptyset(&act.sa_mask);添加sigaddset(&s,SIGUSR1);sigfillset  

                                    int  sa_flags;              接受标志 //接收数据时  需要设置sa_flags = SA_SIGINFO

                                    void  (*sa_restorer)(void);

                       sigset_t   信号集合

                       SA_SIGINFO

                       siginfo_t{

                                    int    si_signo     信号number

                                    int    si_errno       错误值

                                    int     si_code 

                                    int      si_trapno}

                                    pid     si_pid

                                     ........

              union    sigval_t {

                            int sival_int; 

                            void * sival_ptr}

            sigqueue(pid,signum,union sigval aaa)发送信号到指定pid  并且传递一个参数

信号集合操作

           int sigemptyset(sigset_t *set);

           int sigfillset (sigset *set);

           int sigaddset(sigset *set,int signum);

           int sigdelset(sigset *set,int signum);

           int sigismember(const sigset_t *set,int signum);   判断是否存在

           设置屏蔽信号集合

           int sigprocmask(int how,const sigset_t *set,sigse_t *oldset);设置set为屏蔽信号

           SIG_BLOCK设置信号阻塞方式     SIG_UNBLOCK非阻塞    SIG_SETMASK设置为屏蔽集

未决信号

          sigpending(sigset *set);

          

//查看未决信号中有哪些信号
void print_sig(sigset_t *p)
{
    int i=1;
    for(;i<32;i++){
        if(sigismenmber(p,i)){
            printf("1");
        }else {
            printf("0"); 
        }
    }
    printf("\n");
}

sigsuspend(strcut sigset_t *set)   等待信号函数  接收到一个信号  不在set中 该函数返回

简单例子:

#include "stdio.h"
#include <unistd.h>
#include "signal.h"
#include "errno.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

union sigval val;
pid_t pid;
void showprogress(int a, siginfo_t * info, void * data){
        printf("file copy progress:%d\n", info->si_value.sival_int);
        if((info->si_value.sival_int) >1000)
        {
                printf("file copy sucess!!!\n");
                exit(0);
        }
}

void sendsigusr1(int pro)
{
union sigval haha;
haha.sival_int =100; 
     val.sival_int = 100;
     sigqueue(pid,SIGUSR1,haha);
}

int main(int argc,char*argv[])
{
        int readfile,writfile;
        int filesize = 0;
        if(argc<3)
        {
                printf("please stdin enter file name : readfile writfile...");
                exit(0);
        }
        pid = fork();
        if(pid==-1){
                perror("fork error");
                exit(0);
        }else if(pid == 0)
        {
                struct sigaction act;
                printf("haha\n");
                act.sa_flags = SA_SIGINFO;
                act.sa_sigaction = showprogress;
                sigemptyset(&(act.sa_mask));
                sigaction(SIGUSR1,&act,NULL);
                while(1){
                printf("chlid is runing!\n");
                pause();

                }
        }else if(pid>0){
                int progress = 0;
                int i = 0;
                char buf[8];
                val.sival_int = 0;
                if((readfile = open(argv[1],O_RDWR))==-1)
                {
                        perror("open");
                        exit(0);
                }
                if ((writfile = open(argv[2],O_RDWR|O_CREAT))==-1)
                {
                        /* code */perror("open");
                        exit(0);
                }
                filesize = lseek(readfile,0,SEEK_END);
                lseek(readfile,0,SEEK_SET);
                signal(SIGALRM,sendsigusr1);
                //ualarm(1,1);
                while(1)
                {
                        i = read(readfile,buf,1);
                        if(i <=0) {
                                close(readfile);
                                close(writfile);
                                break;
                        }
                        progress+=i;
                        write(writfile,buf,1);

                        val.sival_int = progress;
                        sigqueue(pid,SIGUSR1,val);
                }
                close(readfile);
                close(writfile);
                val.sival_int = -666;
                sigqueue(pid,SIGUSR1,val);
                                              
        }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值