LINUX signal 信號


kill    -1 查看所有信號列表
man  7  signal  主要查看信號行為

信號是進程在運行過程中,由自身產生或由進程外部發過來的消息(事件)信號是硬件中斷的軟件模擬(軟中斷)每個信號用一個整型常量宏表示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是暫停進程。

可以用函數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;
}





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;
}


函數原型:

#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;
}







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM