正在加载……
专注、离线、切勿分心
kill    -1 查看所有信号列表
man  7  signal  主要查看信号行为

1. 信号概念

信号是进程在运行过程中,由自身产生或由进程外部发过来的消息(事件)信号是硬件中断的软件模拟(软中断)每个信号用一个整型常量宏表示SIG开头,比如SIGCHLD( 子进程结束向父进程发送的一个信号 )SIGINT(Ctrl+c)等,它们在系统头文件<signal.h>中定义,可以通过在shell下键入kill –l查看信号列表,或者键入man 7 signal查看更详细的说明。

信号的生成来自内核,让内核生成信号的请求来自3个地方:

l 用户用户能够通过输入CTRL+c(2号信号)Ctrl+\ ( 产生的是三号信号,SIGQUIT )或者是终端驱动程序分配给信号控制字符的其他任何键来请求内核产生信号

l 内核当进程执行出错时,内核会给进程发送一个信号,例如非法段存取(内存访问违规)、浮点数溢出等;

  l 进程:一个进程可以通过系统调用kill给另一个进程发送信号,一个进程可以通过信号和另外一个进程进行通信

     由进程的某个操作产生的信号称为同步信号(synchronous signals),例如除0;由像用户击键这样的进程外部事件产生的信号叫做异步信号(asynchronous signals)

    进程接收到信号以后,可以有如下3种选择进行处理:

l 接收默认处理接收默认处理的进程通常会导致进程本身消亡。例如连接到终端的进程,用户按下CTRL+c,将导致内核向进程发送一个SIGINT的信号,进程如果不对该信号做特殊的处理,系统将采用默认的方式处理该信号,即终止进程的执行; signal(SIGINT,SIG_DFL);

l 忽略信号进程可以通过代码,显示地忽略某个信号的处理,例如:signal(SIGINT,SIG_IGN);但是某被些信号是不能忽略的例如9号信号;

l 捕捉信号并处理:进程可以事先注册信号处理函数,当接收到信号时,由信号处理函数自动捕捉并且处理信号。


   //掌握前31个就行,后面都是实时操作系统里面的

有两个信号既不能被忽略也不能被捕捉,它们是 SIGKILL ( 9号信号 ,比如关机就是给1号进程发送SIGKILL,然后1号进程向系统所有进程发送9号信号 )  SIGSTOP (Ctrl+z 暂停,这样程序才能调试)。即进程接收到这两个信号后,只能接受系统的默认处理,即终止进程SIGSTOP是暂停进程。



2. signal 信号处理机制

可以用函数signal注册一个信号捕捉函数原型为:

#include <signal.h>

typedef void (*sighandler_t)(int);       //函数指针(钩子,也就是回调函数)

sighandler_t  signal(int  signum,  sighandler_t  handler);           //捕捉到信号,但是执行后面函数地址里的函数的代码;signal如果调用成功,返回以前该信号的处理函数的地址,否则返回SIG_ERR

signal的第1个参数signum表示要捕捉的信号,第2个参数是个函数指针表示要对该信号进行捕捉的函数该参数也可以是SIG_DFL(表示交由系统缺省处理,相当于白注册了)SIG_IGN(表示忽略掉该信号而不做任何处理)

             sighandler_t 是信号捕捉函数,由 signal 函数注册,注册以后,在整个进程运行过程中均有效,并且对不同的信号可以注册同一个信号捕捉函数。该函数只有一个整型参数,表示信号值。

signal.c signal_sleep.c
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>

void sig_func(int sig)
{
        printf("sig num=%d\n",sig);
}

int main()
{
        if( signal(SIGINT,sig_func)==SIG_ERR )
        {
                perror("signal");
                return -1;
        }
        while(1);
        return 0;
}
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>

void sig_func(int sig)
{
        printf("before sleep ,sig=%d is coming\n",sig);
        sleep(3);
        printf("after sleep ,sig=%d is coming\n",sig);
}
int main()
{
        if( signal(SIGINT,sig_func)==SIG_ERR )
        {
                perror("signal");
                return -1;
        }
        if( signal(SIGQUIT,sig_func)==SIG_ERR )
        {
                perror("signal");
                return -1;
        }
        while(1);
        return 0;
}
先来一个信号马上打印,后面来其他信号就会打断当前操作,去执行后面来的信号,然后再返回刚才打断程序接着运行
内核针对信号存储每个信号只有一个位置
1、signal针对相同的信号,执行流程不能重入
2、signal不同信号来了,打断原有信号处理流程
内核维护一个信号集合,一直在检测,当有信号发生,内核检测到,把对应的信号标志位置1,执行对应的处理函数。当在执行信号处理函数时,相同的信号又发生,但是对应位已经置1,系统就会忽略;如果是其他信号,同样,修改对应标志位,执行对应信号处理函数。处理完再返回上次被打断的执行代码处接着执行;
signal_ign.c
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>

void sig_func(int sig)
{
        printf("sig=%d is coming\n",sig);
}

int main()
{
        if(signal(SIGINT,SIG_IGN)==SIG_ERR)
        {
                perror("signal");
                return -1;
        }
        if(signal(SIGQUIT,sig_func)==SIG_ERR)
        {
                perror("signal");
                return -1;
        }
        while(1);
        return 0;
}





3. sigaction信号处理机制

signal处理机制下,还有许多特殊情况需要考虑:

1、  注册一个信号处理函数,并且处理完毕一个信号之后,是否需要重新注册,才能够捕捉下一个信号;(不需要)

2、  如果信号处理函数正在处理信号,并且还没有处理完毕时,又发生了一个同类型的信号,这时该怎么处理;(接着执行),后续相同信号忽略(会多执行一次)。

3、  如果信号处理函数正在处理信号,并且还没有处理完毕时,又发生了一个不同类型的信号,这时该怎么处理;(跳转去执行另一个信号,之后再执行剩下的没有处理完的信号) 

4、  如果程序阻塞在一个系统调用 ( 如read(...) ) 时,发生了一个信号,这时是让系统调用返回错误再接着进入信号处理函数,还是先跳转到信号处理函数,等信号处理完毕后,系统调用再返回。(后者)

df 
signal_read.c
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>

void sig_func(int sig)
{
        printf("before sleep ,sig=%d is coming\n",sig);
        sleep(3);
        printf("after sleep ,sig=%d is coming\n",sig);
}
int main()
{
        if( signal(SIGINT,sig_func )==SIG_ERR )
        {
                perror("signal");
                return -1;
        }
        if( signal(SIGQUIT,sig_func)==SIG_ERR )
        {
                perror("signal");
                return -1;
        }
        char buf[128]={0};
        read(0,buf,sizeof(buf));
        printf("buf=%s\n",buf);
        return 0;
}


3.2. sigaction 信号处理注册

函数原型:

#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);   //函数调用成功,将返回0,否则返回-1

sigaction也用于注册一个信号处理函数

参数signum为需要捕捉的信号

参数act是一个结构体,里面包含信号处理函数地址处理方式等信息

参数oldact是一个传出参数sigaction函数调用成功后,oldact里面包含以前对signum的处理方式的信息,通常为NULL

如果函数调用成功,将返回0,否则返回-1

结构体 struct sigaction (注意名称与函数sigaction相同)原型为:

struct sigaction
{

       void (*sa_handler)(int);                              //老类型的信号处理函数指针,不用,我们用最新的

       void (*sa_sigaction)(int, siginfo_t *, void *);       //新类型的信号处理函数指针

       sigset_t sa_mask;                                     //将要被阻塞的信号集合(sigset_t)

       int sa_flags;                                         //信号处理方式掩码 ( SA_SIGINFO )

       void (*sa_restorer)(void);                            //保留,不要使用

};

该结构体的各字段含义及使用方式:

1字段sa_handler是一个函数指针用于指向原型为void handler(int)的信号处理函数地址,老类型的信号处理函数(如果用这个再将sa_flags = 0,就等同于signal()函数)

2字段sa_sigaction也是一个函数指针,用于指向原型为:

void handler(int iSignNum, siginfo_t  *pSignInfo, void *pReserved);        的信号处理函数,即新类型的信号处理函数

该函数的三个参数含义为:

             iSignNum 传入的信号

             pSignInfo与该信号相关的一些信息,它是个结构体

            pReserved保留,现没用,通常为NULL

3字段 sa_handler 和 sa_sigaction 只应该有一个生效,如果想采用老的信号处理机制,就应该让 sa_handler 指向正确的信号处理函数,并且让字段 sa_flags 0;否则应该让 sa_sigaction 指向正确的信号处理函数,并且让字段sa_flags包含SA_SIGINFO选项

4字段sa_mask是一个包含信号集合的结构体该结构体内的信号表示在进行信号处理时,将要被阻塞的信号针对 sigset_t 结构体,有一组专门的函数对它进行处理,它们是:

   sigset_t sa_mask;          //将要被阻塞的信号集合

        #include <signal.h>

     int sigemptyset(sigset_t *set);                      //清空信号集合set

     int sigfillset(sigset_t *set);                       //将所有信号填充进set

     int sigaddset(sigset_t *set, int signum);            //set中添加信号signum

     int sigdelset(sigset_t *set, int signum);            //set中移除信号signum

     int sigismember(const sigset_t *set, int signum);    //判断signum是否包含在set(:返回1,:0

     int sigpending(sigset_t *set);                       //将被阻塞的信号集合由参数set指针返回(挂起信号) //成功返回 0 , 失败返回 -1 .

      ****** 其中,对于函数sigismember而言,如果signumset集中,则返回1;不在,则返回0;出错时返回-1其他的函数都是成功返回0失败返回-1.


  例如,如果打算在处理信号SIGINT时,只阻塞对SIGQUIT信号的处理,可以用如下方法:

        struct sigaction act;

    act.sa_flags = SA_SIGINFO;

    act.sa_sigaction = newHandler;     //newHandler参数指定

    sigemptyset(&act.sa_mask);

    sigaddset(&act.sa_mask, SIGQUIT);

    sigaction(SIGINT,&act,NULL);

通过   man  sigaction     查看 siginfo_t 的结构体

      5、  字段sa_flags是一组掩码的合成值,指示信号处理时所应该采取的一些行为,各掩码的含义为:

掩码    描述
SA_RESETHAND 处理完毕要捕捉的信号后,自动撤消信号处理函数的注册,即必须再重新注册信号处理函数,才能继续处理接下来产生的信号。该选项不符合一般的信号处理流程,现已经被废弃。
SA_NODEFER 处理信号时,如果又发生了其它的信号,则立即进入其它信号的处理,等其它信号处理完毕后,再继续处理当前的信号,即递规地处理。(不常用)不断重入,次数不丢失
SA_RESTART 如果在发生信号时,程序正阻塞在某个系统调用,例如调用read()函数,则在处理完毕信号后,接着从阻塞的系统返回。如果不指定该参数,中断处理完毕之后,read函数读取失败。
SA_SIGINFO 指示结构体的信号处理函数指针是哪个有效,如果sa_flags包含该掩码,则 sa_sigaction 指针有效,否则是 sa_handler 指针有效。(常用)


sigaction.c
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void sig(int signum,siginfo_t* p,void* p1)
{
        printf("signum=%d is coming\n",signum);
}

int main()
{
        struct sigaction act;
        bzero(&act,sizeof(act));
        act.sa_sigaction=sig;
        act.sa_flags=SA_SIGINFO;         //act.sa_flags=SA_SIGINFO|SA_RESTART;
        int ret=sigaction(SIGINT,&act,NULL);
        if(-1==ret)
        {
                perror("sigaction");
                return -1;
        }
        while(1);                // char buf[128]={0};   read(0,buf,sizeof(buf));    printf("buf=%s\n",buf);
        return 0;
}


//不设置 act.sa_flags=SA_SIGINFO|SA_RESTART;

//阻塞等待输入,如果在输入之前有信号中断,中断处理完就直接退出了

//设置




sigaction_mask.c
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

void sig(int signum,siginfo_t* p,void* p1)
{
        printf("before signum=%d is coming\n",signum);
        sleep(3);
        printf("after signum=%d is coming\n",signum);
}

int main()
{
        struct sigaction act;
        bzero(&act,sizeof(act));
        act.sa_sigaction=sig;
        act.sa_flags=SA_SIGINFO|SA_RESTART;
       int  ret=sigaddset(&act.sa_mask,SIGQUIT);         //sigaction执行中屏蔽SIGQUIT信号,不受影响,执行完后再执行过程中发生的SIGQUIT信号操作
        if(-1==ret)
        {
                perror("sigaddset");
                return -1;
        }
        ret=sigaction(SIGINT,&act,NULL);
        if(-1==ret)
        {
                perror("sigaction");
                return -1;
        }
       while(1);
       return 0;
}






  siginfo_t {
               int      si_signo;      /* Signal number */
               int      si_errno;      /* An errno value */
               int      si_code;      /* Signal code */
               int      si_trapno;   /* Trap number that caused hardware-generated signal    (unused on most architectures) */
               pid_t    si_pid;     /* Sending process ID */
               uid_t    si_uid;      /* Real user ID of sending process */
            
          
              int      si_status;     /* Exit value or signal */
              clock_t  si_utime;   /* User time consumed */
              clock_t  si_stime;    /* System time consumed */
              sigval_t si_value;    /*  Signal value */
              int      si_int;          /*  POSIX.1b signal */
              void    *si_ptr;       /*  POSIX.1b signal */
              int      si_overrun;  /* Timer overrun count ; POSIX.1b timers */
              int      si_timerid;   /* Timer ID; POSIX.1b timers */
              void    *si_addr;     /* Memory location which caused fault */
              long    si_band;      /* Band event (was int in  glibc 2.3.2 and earlier) */
             int      si_fd;               /* File descriptor */
             short    si_addr_lsb;    /* Least significant bit of address (since Linux 2.6.32) */
             void    *si_call_addr;   /* Address of system call instruction (since Linux 3.5) */
              int      si_syscall;        /* Number of attempted system call (since Linux 3.5) */
              unsigned int si_arch;  /* Architecture of attempted system call (since Linux 3.5) */
}

sigaction_siginfo.c
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void sig(int signum,siginfo_t* p,void* p1)
{
        printf("signum=%d is coming\n",signum);
        printf("sending signal process id=%d\n",p->si_pid);
        printf("sending signal user id=%d\n",p->si_uid);
}

int main()
{
        struct sigaction act;
        bzero(&act,sizeof(act));
        act.sa_sigaction=sig;
        act.sa_flags=SA_SIGINFO;                                 
        int ret=sigaction(SIGINT,&act,NULL);
        if(-1==ret)
        {
                perror("sigaction");
                return -1;
        }
        while(1);                                                       
        return 0;
}



//本窗口: id都为0,在其他窗口 kil -2 进程号id(表示向该进程发送2号信号(SIGINT)) 进程的id就是它自己,为用户id为当前登录用户


sleep 函数的是实现是采用让进程什么都不执行,等到过了给定的时间后,会产生一个SIGALRM信号,这个时候唤醒进程接着执行;但是在等待SIGALRM信号的时候有其他信号发生,并被注册,那么进程直接唤醒,提前结束睡眠;


3.3. sigprocmask信号阻塞

函数sigaction设置的被阻塞信号集合只是针对于要处理的信号,例如

struct sigaction act;

sigemptyset(&act.sa_mask);

sigaddset(&act.sa_mask,SIGQUIT);

sigaction(SIGINT,&act,NULL);

 表示只有在处理信号SIGINT才阻塞信号SIGQUIT(重点区分)

  

               函数sigprocmask全程阻塞sigprocmask中设置了阻塞集合后被阻塞的信号将不能再被信号处理函数捕捉直到重新设置阻塞信号集合

原型为

          #include <signal.h>
      int sigprocmask(int how, const sigset_t  *set, sigset_t *oldset);  //成功返回0,失败返回-1。

参数how    的值为如下3者之一

       aSIG_BLOCK ,将参数2的信号集合添加到进程原有的阻塞信号集合中

       bSIG_UNBLOCK ,从进程原有的阻塞信号集合移除参数2中包含的信号

       cSIG_SETMASK重新设置进程的阻塞信号集为参数2的信号集

参数set   为阻塞信号集

参数oldset   是传出参数,存放进程原有的信号集,通常为NULL


sigprocmask.c sigpro_pending.c
#include<stdio.h>
#include<signal.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
void sigFunc(int sig,siginfo_t *p,void *p1)
{
        printf("before sleep , signum=%d\n",sig);
        sleep(3);
        printf("after sleep , signum=%d\n",sig);
}
int main(void)
{
        sigset_t set;
        memset(&set,0,sizeof(set));
        sigaddset(&set,SIGINT);
        int ret = sigprocmask(SIG_BLOCK,&set,NULL);
        if(-1==ret)
        {
                perror("sigprocmask");
                exit(-1);
        }
        struct sigaction act;
        memset(&act,0,sizeof(act));
        act.sa_sigaction = sigFunc;
        act.sa_flags = SA_SIGINFO | SA_RESTART;
        sigemptyset(&act.sa_mask);
        ret = sigaction(SIGINT,&act,NULL);
        if(-1==ret)
        {
                perror("sigaction");
                exit(-1);
        }
        //while(1);
        sleep(5);
        printf("\nafter sleep , unblock SIG_INT\n");
        ret=sigismember(&set,SIGINT);   //查看信号SIGINT在不在指定集合中
        if(ret !=1)
        {
                return -1;
        }
        sigprocmask(SIG_UNBLOCK,&set,NULL);
        while(1);
        return 0;
}


//将被阻塞的信号集合由参数set指针返回(挂起信号)
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
        sigset_t set;
        sigemptyset(&set);
        sigaddset(&set,SIGINT);
        int ret ;
        ret=sigprocmask(SIG_BLOCK,&set,NULL);
        if(-1==ret)
        {
                perror("sigprocmask");
                return -1;
        }
        sleep(5);
        sigemptyset(&set);        //把集合set清空
        ret =sigpending(&set);    //把阻塞的信号拿出来放到set中,有阻塞信号返回1,没有返回0
//这个阻塞不是前面设定好,就会找到,是设置好阻塞,在执行过程中触发了这个信号,但是没有处理,内核记录了这个信号发生。俗称挂起。
        ret = sigismember(&set,SIGINT);
        if(1==ret)
        {
                printf("SIGINT is in the set\n");
        }
        if(0==ret)
        {
                printf("SIGINT is not in the set\n");
        }
        return 0;
}



sigaction_mask_pending.c
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

void sig(int signum,siginfo_t* p,void* p1)
{
                printf("before signum=%d\n",signum);
                sleep(3);
                sigset_t set;
                sigemptyset(&set);
                sigpending(&set);
                if( sigismember(&set,SIGQUIT) )
                {
                        printf("SIGQUIT is come , but pending\n");
                }
                else
                {
                        printf("SIGQUIT is not come\n");
                }
                printf("after signum=%d\n",signum);
}

int main()
{
        struct sigaction act;
        bzero(&act,sizeof(act));
        act.sa_sigaction=sig;
        act.sa_flags=SA_SIGINFO|SA_RESTART;
        int ret;
        ret=sigaddset(&act.sa_mask,SIGQUIT);         //sigaction执行中屏蔽SIGQUIT信号,不受影响,执行完后在来执行相应操作
        if(-1==ret)
        {
                perror("sigaddset");
                return -1;
        }
        ret=sigaction(SIGINT,&act,NULL);
        if(-1==ret)
        {
                perror("sigaction");
                return -1;
        }
       while(1);
       return 0;
}





4.  用程序发送信号

kill.c  kill0.c
#include<sys/types.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>

int main(int argc,char* argv[])
{
        if(argc!=2)
        {
                printf("error args\n");
                return -1;
        }
        pid_t pid;
        pid=atoi(argv[1]);            //传递一个进程id号
        int ret =kill(pid,SIGINT);
        if(-1==ret)
        {
                perror("kill");
                return -1;
        }
        return 0;
}
#include<sys/types.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>

int main()
{
        if(!fork())
        {
              printf("I am child\n");
              while(1);
        }
        else
        {
                printf("I am parent\n");
                sleep(10);
                int ret=kill(0,SIGINT);
                if(-1==ret)
                {
                       perror("kill");
                       return -1;
                }
                wait(NULL);
                printf("wait is execute\n");
        }
        return 0;
}





5.1.睡眠函数

    #include <unistd.h>
   unsigned int sleep(unsigned int seconds);
   void usleep(unsigned long usec);

函数sleep 让进程睡眠 seconds ,函数 usleep 让进程睡眠 usec 微秒
    sleep 睡眠函数内部是用信号机制进行处理的,用到的函数有:

   #include <unistd.h>
   unsigned int alarm(unsigned int seconds);//告知自身进程,要进程在 seconds 秒后自动产生一个 SIGALRM 的信号。
  int pause(void);   //将自身进程挂起,直到有信号发生时才从 pause 

alarm.c pause.c
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
//设定SIGALRM信号的处理行为,alarm(3),while(1)
void sigFunc(int sig)
{
        printf("I am sig %d\n",sig);
}
int main(void)
{
        signal(SIGALRM,sigFunc);
        sleep(3);   //等待3秒
        printf("sleep over\n");
        alarm(1);
        printf("alarm over\n");
        while(1);   //3秒时候才产生一个SIGALRM信号,所以一定要等,不然程序结束了,看不到对应输出了
        return 0;
}
#include<unistd.h>

int main()
{
        pause();
        return 0;
}





Linux为每个进程维护3个计时器,分别是真实计时器虚拟计时器实用计时器

l        真实计时器计算的是程序运行的实际时间---直接

l 虚拟计时器计算的是程序运行在用户态时所消耗的时间可认为是实际时间减掉(系统调用和程序睡眠所消耗)的时间 )---需要了解内核

l 实用计时器计算的是程序处于用户态和处于内核态所消耗的时间之和。(睡觉就不算)---常用

例如:有一程序运行,在用户态运行了5秒,在内核态运行了6秒,还睡眠了7秒,则真实计算器计算的结果是18秒,虚拟计时器计算的是5秒,实用计时器计算的是11秒。


用指定的初始间隔和重复间隔时间为进程设定好一个计时器后,该计时器就会定时地向进程发送时钟信号3个计时器发送的时钟信号分别为:SIGALRM SIGVTALRM 和 SIGPROF 


用到的函数与数据结构:

#include <sys/time.h>

1. int getitimer(int which, struct itimerval *value);                  //获取计时器的设置;成功返回 0 , 失败返回 -1 ;

参数which 指定哪个计时器,可选项为ITIMER_REAL(真实计时器)ITIMER_VIRTUAL(虚拟计时器ITIMER_PROF(实用计时器))

参数value 为一结构体的传出参数用于传出该计时器的初始间隔时间和重复间隔时间

返回值:如果成功,返回0,否则-1

2int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);                   //设置计时器 ; 成功返回 0,失败返回 -1 ;

参数which 指定哪个计时器,可选项为ITIMER_REAL(真实计时器)ITIMER_VIRTUAL(虚拟计时器、ITIMER_PROF(实用计时器))

参数value 为一结构体的传入参数指定该计时器的初始间隔时间和重复间隔时间

参数ovalue 为一结构体传出参数,用于传出以前的计时器时间设置(NULL)

返回值:如果成功,返回0,否则-1

struct  itimerval 
{

   struct timeval   it_interval;     /* next value */         //重复间隔

   struct timeval   it_value;        /* current value */      //初始间隔

};
//初始间隔就是隔多少秒,发送SIGALRM信号;重复间隔就是以后每隔多少时间再发送SIGALRM信号
struct  timeval 
{

           long tv_sec;   /* seconds */         //时间的秒数部分

           long tv_usec;  /* microseconds */    //时间的微秒部分 

};


setitimer.c     //启用真实计时器的进行时钟处理(获得当前系统时间,并一秒更新一次)
#include<sys/time.h>
#include<signal.h>
#include<stdio.h>
#include<time.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>

void sig_handle(int sig)
{
        time_t t;
        time(&t);  //取当前秒数;
        struct tm* p=gmtime(&t);  //ctime();很简单,这里就不用了;用的格林威治时间;
        printf("%2d:%2d:%d\n",p->tm_hour,p->tm_min,p->tm_sec);
}
int main()
{
        signal(SIGALRM,sig_handle); 
        kill(0,SIGALRM);   //为了设定timer之前,就发一个SIGALRM信号打印时间,看看后面是不是间隔5秒发送SIGALRM信号,我们可以用kill来发送,当前运行程序的窗口id就是0;
        //sig_handle(0);   //参数随便传
        struct itimerval rt;
        memset(&rt,0,sizeof(rt));  //这里全部赋0,后面就不用设置微妙0了;
        rt.it_value.tv_sec=5;
        rt.it_interval.tv_sec=2;   //设置初始间隔和重复间隔,微秒我们也感应不出来,就不设置了;也可以设置为0 ;
        int ret=setitimer(ITIMER_REAL,&rt,NULL);
        if(-1==ret)
        {
                perror("setitimer");
                return -1;
        }
        while(1);
        return 0;
}






posted on 2018-03-03 14:05  正在加载……  阅读(2214)  评论(0编辑  收藏  举报