• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            大龍的博客

            常用鏈接

            統(tǒng)計(jì)

            最新評(píng)論

            Linux C語言 信號(hào)及信號(hào)的操作

            一.信號(hào)
             1.信號(hào)的作用
              1.1.控制進(jìn)程
              1.2.實(shí)現(xiàn)簡單的多任務(wù)
              1.3.進(jìn)程間交換數(shù)據(jù)
             2.什么是信號(hào)
              2.1.信號(hào)是一個(gè)整數(shù)
                kill -l
              2.2.信號(hào)是軟中斷(模擬中斷)
                中斷就是在進(jìn)行某個(gè)過程,隨時(shí)停下來,并進(jìn)行其他過程,當(dāng)其他過程結(jié)束后回到原來過程的現(xiàn)象。
              2.3.信號(hào)的工作原理
                信號(hào)源(操作系統(tǒng),硬件,用戶程序)發(fā)出信號(hào)
                系統(tǒng)接收到信號(hào)(信號(hào)),系統(tǒng)查找信號(hào)的注冊表,并找到該進(jìn)程(信號(hào)目的地)對(duì)應(yīng)的信號(hào)處理函數(shù)(中斷函數(shù)),停止原進(jìn)程的實(shí)現(xiàn),執(zhí)行信號(hào)處理函數(shù),執(zhí)行完畢,繼續(xù)原進(jìn)程的執(zhí)行。
                
                信號(hào)與信號(hào)處理函數(shù)注冊必須缺省哪個(gè)進(jìn)程。
                a.信號(hào)源(系統(tǒng)進(jìn)程,用戶進(jìn)程)
                b.信號(hào)目的地(進(jìn)程)
                c.信號(hào)(有特殊含義的整數(shù))
                d.信號(hào)處理函數(shù)(函數(shù)void(*)(int))
              2.4.信號(hào)分類
                不可靠信號(hào)1-31(非實(shí)時(shí)信號(hào))
                可靠信號(hào)34-64(實(shí)時(shí)信號(hào))
              2.5.信號(hào)的編程模型:
                發(fā)送信號(hào):kill函數(shù);或者其他鍵盤操作。
                信號(hào)處理函數(shù):void(*)(int);    
                注冊信號(hào):signal函數(shù)
            案例:
              體會(huì)信號(hào)SIGINT=2。
              處理信號(hào)2
            結(jié)論:
              1.信號(hào)如果用戶不處理,系統(tǒng)會(huì)缺省處理    
                系統(tǒng)的缺省處理大部分情況,是輸出信號(hào)含義,并終止進(jìn)程。
                信號(hào)有缺省處理,也有忽略處理
                SIG_IGN  特殊的信號(hào)處理函數(shù)-忽略信號(hào)1
                (void(*)(int))1
                SIG_DFL  特殊的信號(hào)處理函數(shù)-缺省處理0
                (void(*)(int))0
              2.sleep,pause函數(shù)被信號(hào)中斷后,不會(huì)再繼續(xù),而是返回.
                函數(shù)類型:
                可重入函數(shù):
                  中斷后可繼續(xù)執(zhí)行的函數(shù)
                不可重入函數(shù):
                  中斷后函數(shù)不繼續(xù)執(zhí)行,而是返回結(jié)束。
              
              信號(hào)中斷會(huì)導(dǎo)致什么安全問題?
                多線程本身就是數(shù)據(jù)不安全的。
                
              2.6.發(fā)送信號(hào)
                int   kill(pid_t pid,//信號(hào)的目的地進(jìn)程
                   int sig);//信號(hào)
                參數(shù)1:
                   >0:進(jìn)程ID
                   =0:同一個(gè)進(jìn)程組的所有進(jìn)程
                   -1:所有進(jìn)程
                   <-1:進(jìn)程組為|pid|的所有進(jìn)程
            案例:
               使用kill發(fā)送信號(hào)
            結(jié)論:
               1.在獨(dú)立兩個(gè)進(jìn)程之間,使用信號(hào)通信需要知道另外一個(gè)進(jìn)程ID。
               2.1-31之間的信號(hào)是不可靠。
                34-64信號(hào)是可靠的。
              2.7.案例:使用信號(hào)控制進(jìn)程。
                 使用信號(hào)修改搖獎(jiǎng)程序。
              
              2.8.案例:使用信號(hào)實(shí)現(xiàn)簡單的多任務(wù)。
               2.8.1.簡易版本的信號(hào)發(fā)送函數(shù)
                 int raise(int sec)  向本進(jìn)程發(fā)送信號(hào)
                 =int kill(getpid(),int sec);     
               2.8.2.準(zhǔn)備工作:定時(shí)器信號(hào)
                 alarm    延時(shí)定時(shí)器
                  向系統(tǒng)注冊,在指定的時(shí)間秒后發(fā)送一次SIGALRM信號(hào)。
                 setitimer  間隔定時(shí)器
                  向系統(tǒng)注冊,在指定的時(shí)間微秒后每隔一個(gè)間隔時(shí)間向進(jìn)程發(fā)送信號(hào)SIGALRM。
            int setitimer(int which,//定時(shí)器計(jì)時(shí)方法
              const struct itimerval *val,//延時(shí)與間隔時(shí)間
              struct itimerval *oldval);//返回上次設(shè)置值
               
            struct   itimerval
            {
             struct  timeval it_interval;//間隔時(shí)間
             struct timeval  it_value;//延時(shí)時(shí)間
            }     
            struct timeval
            {
             long tv_sec;//秒
             long tv_usec;//微秒
            }
            定時(shí)器計(jì)時(shí)方法:
               ITIMER_REAL    真實(shí)時(shí)間
                   SIGALRM
               ITIMER_VIRTUAL  進(jìn)程實(shí)際運(yùn)行時(shí)間
                   SIGVTALRM
               ITIMER_PROF    進(jìn)程時(shí)間+內(nèi)核時(shí)間
                   SIGPROF
               
                 案例1:使用alarm設(shè)置系統(tǒng)的信號(hào)發(fā)送參數(shù)案例2:使用setitimer設(shè)置間隔定時(shí)時(shí)間
                 結(jié)論:想馬上發(fā)送信號(hào),不要把it_value設(shè)置為0秒0微秒,而是設(shè)置為0秒1微秒。  
               2.8.3.使用定時(shí)器實(shí)現(xiàn)與時(shí)間有關(guān)的子任務(wù)
                案例:
                  顯示7位隨機(jī)數(shù)與時(shí)間。
                方法:
                  一個(gè)進(jìn)程+定時(shí)器信號(hào)。      
             2.9.信號(hào)的操作
               2.9.1.信號(hào)屏蔽
               使用signal把某個(gè)信號(hào)忽略。只能對(duì)單個(gè)的信號(hào)處理,處理多個(gè)信號(hào),需要反復(fù)調(diào)用signal函數(shù)
               a.背景:
                 信號(hào)屏蔽的意義。
                 保護(hù)一段代碼不受信號(hào)的中斷影響。
                 等代碼執(zhí)行結(jié)束再處理信號(hào)。[信號(hào)不丟失,但被系統(tǒng)延遲處理]
               b.信號(hào)屏蔽函數(shù)
              int sigprocmask(int how,//信號(hào)操作方式
               const sigset_t *sigs,//操作的信號(hào)集合
               sigset_t *oldsigs);//返回原來的信號(hào)集合
              信號(hào)的操作方式:
                SIG_BLOCK  屏蔽信號(hào)
                SIG_UNBLOCK 解除信號(hào)屏蔽
                SIG_SETMASK 修改屏蔽信號(hào)
               
               sigset_t數(shù)據(jù)集合的操作:
                清空信號(hào)集合sigemptyset
                添加信號(hào)到集合sigaddset
                刪除集合中的某個(gè)信號(hào)sigdelset
                判定某個(gè)信號(hào)是否在集合中sigismember
                把所有信號(hào)添加到信號(hào)集合sigfillset
               編程模型:
                 定義信號(hào)集合sigset_t sigs;
                 初始化信號(hào)集合empty add del fill
                 設(shè)置屏蔽信號(hào)sigprocmask  SIG_BLOCK
                 解除屏蔽信號(hào)sigprocmask SIG_UNBLOCK
                 判定某個(gè)信號(hào)是否在集合中ismember 
               SIGSTOP   SIGKILL
               2.9.2.查詢被屏蔽的信號(hào)是否發(fā)生
               背景:
                 在被屏蔽代碼中,怎么知道被屏蔽的信號(hào)已經(jīng)發(fā)生?
               函數(shù):
                 int sigpending(sigset_t *sigs);//返回發(fā)生的信號(hào),而且該信號(hào)被屏蔽。
               問題:
                 信號(hào)屏蔽的時(shí)候,信號(hào)發(fā)送,信號(hào)不被處理,解除信號(hào)屏蔽,信號(hào)才被處理。
                 在信號(hào)屏蔽中,能否處理信號(hào)?
                 答案:能
               問題:怎么處理?
                 答案:解除屏蔽,然后再屏蔽。
               問題:
                 信號(hào)屏蔽與解除屏蔽瞬間,其他信號(hào)是否會(huì)發(fā)生,導(dǎo)致程序解除。
                 信號(hào)處理函數(shù)在執(zhí)行中,是否會(huì)被信號(hào)影響?肯定影響(本身信號(hào)不影響,被其他信號(hào)影響。)
                 
               2.9.3.防止信號(hào)處理函數(shù)執(zhí)行中被信號(hào)影響。
                 a.sigsuspend函數(shù)設(shè)置屏蔽信號(hào)
                  該函數(shù)的作用:等待信號(hào)發(fā)生,當(dāng)信號(hào)發(fā)生,并且設(shè)置新的屏蔽信號(hào),執(zhí)行信號(hào)處理函數(shù),執(zhí)行完畢,解除信號(hào)屏蔽,恢復(fù)原來的信號(hào)屏蔽,函數(shù)返回。
                  int sigsuspend(const sigset_t*);
                  等待信號(hào):任意信號(hào)。
                  在等待過程中,不受參數(shù)設(shè)置的信號(hào)集合中的信號(hào)影響。
                  當(dāng)信號(hào)發(fā)生,處理信號(hào),同樣不受參數(shù)設(shè)置的信號(hào)影響。
                  信號(hào)處理結(jié)束,sigsuspend恢復(fù)原來的信號(hào)屏蔽,并且sigsuspend返回。
                  
                  sigsuspend該函數(shù)等待信號(hào),沒有信號(hào)發(fā)生,該函數(shù)阻塞。信號(hào)發(fā)生,則處理后返回。
                 結(jié)論:
                   1.sigsuspend 解除原來的所有信號(hào)屏蔽
                   2.沒有信號(hào)發(fā)生,sigsuspend阻塞。
                   3.sigsuspend返回前,會(huì)恢復(fù)解除屏蔽的信號(hào)
                   4.在解除原來的信號(hào)屏蔽,設(shè)置新的信號(hào)屏蔽。
                   5.函數(shù)結(jié)束前,解除新的信號(hào)屏蔽
            int sigsuspend(sigset_t *sig)
            {
             1.sigprocmask(SIG_UNBLOCK,*s,0);
             2.sigprocmask(SIG_BLOCK,*sig,0);
             3.等待信號(hào)發(fā)生pause
             4.處理信號(hào)
             5.sigprocmask(SIG_UNBLOCK,*sig,0);
             6.sigprocmask(SIG_BLOCK,*s,0);
             7.return 0;
            }        
              sigsuspend未必一定要在sigprocmask環(huán)境下工作

            案例:
              利用sigsuspend控制進(jìn)程.
            作業(yè):
              1.實(shí)現(xiàn)搖獎(jiǎng)。
                要求:時(shí)間顯示使用SIALRM信號(hào)。
                控制:使用sigsuspend控制隨機(jī)數(shù)進(jìn)程。

            注意:
              使用信號(hào)控制進(jìn)程.強(qiáng)烈建議:
                sigsuspend + signal + kill
              不推薦
                while(1);+signal+kill
                pause/sleep+signal+kill  

            sigsuspend有兩個(gè)作用:
              定點(diǎn)信號(hào)處理。(屏蔽信號(hào)切換具備原子性)
              控制進(jìn)程。
                 b.高級(jí)信號(hào)發(fā)送與處理函數(shù)處理信號(hào)。

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

            void handle(int s){
             printf("信號(hào)發(fā)生.....\n");
            }
            main()
            {
             signal(45,handle);
             /*printf("%d:%d\n",SIG_IGN,SIG_DFL);*/
             /*signal(SIGINT,SIG_IGN);*/
             while(1){
              /*printf("Hello信號(hào)!\n");*/
              /*sleep(1);*/
             }
            }

             

            #include <unistd.h>
            #include <stdio.h>
            #include <signal.h>
            main()
            {
             int i;
             for(i=0;i<10;i++){
              kill(4095,45);
             }
            }

             

             

            #include <curses.h>
            #include <unistd.h>
            #include <stdlib.h>
            #include <sys/mman.h>
            #include <math.h>
            #include <time.h>

            int isstop=0;
            void handle(){
             isstop=isstop==1?0:1;
            }
            main()
            {
             /*變量區(qū)*/
             int i;
             sigset_t si;
             WINDOW *wtime,*wcode;
             pid_t pid_time,pid_code;
             pid_t pid_sub;
             initscr();
             sigfillset(&si);
             sigdelset(&si,34);
             noecho();
             curs_set(0); 
             wtime=derwin(stdscr,3,10,0,COLS-10);
             wcode=derwin(stdscr,3,9,(LINES-3)/2,(COLS-9)/2);
             keypad(stdscr,TRUE);
             keypad(wtime,TRUE);
             keypad(wcode,TRUE);
             box(wtime,0,0);
             box(wcode,0,0);
             refresh();
             wrefresh(wtime);
             wrefresh(wcode); 
             for(i=0;i<2;i++){
              if(pid_sub=fork())
              {
               if(i==0){
                pid_time=pid_sub;
               }
               if(i==1){
                pid_code=pid_sub;
               }
               continue;
              }
              else
              {
               if(i==0){
                /*子進(jìn)程1:時(shí)間顯示*/
                time_t tt;
                struct tm *t;
                while(1){
                 tt=time(0);
                 t=localtime(&tt);
                 mvwprintw(wtime,1,1,"%02d:%02d:%02d",
                      t->tm_hour,t->tm_min,t->tm_sec);
                 refresh();
                 wrefresh(wcode);
                 wrefresh(wtime);
                 sleep(1);
                }
                exit(0);
               }
               if(i==1){
                /*子進(jìn)程2:隨機(jī)數(shù)顯示*/
                int num; 
                signal(34,handle);   
                while(1){
                 if(isstop){
                  sigsuspend(&si);      
                 }
                 num=rand()%10000000;
                 mvwprintw(wcode,1,1,"%07u",num);
                 refresh();
                 wrefresh(wtime);
                 wrefresh(wcode);
                 usleep(10000);
                }
                exit(0);
               }
              }   
             }
             /*主進(jìn)程:鍵盤輸入*/
             int ch;
             while(1){
              ch=getch();
              if(ch=='\n'){
               /*停止隨機(jī)數(shù)進(jìn)程*/
               /*發(fā)送信號(hào):可靠信號(hào)>=34*/
               kill(pid_code,34);
              }
              /*退出整個(gè)任務(wù)*/
              if(ch=='x' || ch=='X'){
               /*通知子進(jìn)程結(jié)束*/   
               sched_yield();
               break;
              }
             }
             wait(0);
             wait(0);
             delwin(wtime);
             delwin(wcode);
             endwin();
             exit(0); 
            }

            posted on 2011-11-05 05:06 大龍 閱讀(745) 評(píng)論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            亚洲国产精品无码久久SM| 久久久久久精品久久久久| 7777精品久久久大香线蕉| 亚洲综合久久夜AV | 久久免费国产精品| 久久久噜噜噜久久| 久久久噜噜噜久久中文字幕色伊伊| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区| 无码AV中文字幕久久专区| 无码超乳爆乳中文字幕久久 | 综合网日日天干夜夜久久| 亚洲中文字幕久久精品无码APP | 波多野结衣AV无码久久一区| 无码久久精品国产亚洲Av影片| 久久综合给合久久狠狠狠97色69| 久久久久久亚洲Av无码精品专口| 国产婷婷成人久久Av免费高清| 精品午夜久久福利大片| 精品人妻伦九区久久AAA片69 | 久久精品二区| 久久99国产精品久久99小说| 欧美亚洲色综久久精品国产| 精品久久久久久| 欧洲国产伦久久久久久久| 亚洲精品国产美女久久久| 久久天堂电影网| 久久久久av无码免费网| 国产精品一区二区久久| 亚洲?V乱码久久精品蜜桃 | 亚洲七七久久精品中文国产| 97久久婷婷五月综合色d啪蜜芽 | 久久亚洲视频| 97热久久免费频精品99| 精品久久人人妻人人做精品| 久久婷婷五月综合色高清| 久久久无码精品午夜| 97久久超碰成人精品网站| 久久综合鬼色88久久精品综合自在自线噜噜 | 久久精品无码专区免费| 久久久免费精品re6| 2021久久精品免费观看|