• <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)計

            最新評論

            Linux C語言 信號及信號的操作

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

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

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

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

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

            void handle(int s){
             printf("信號發(fā)生.....\n");
            }
            main()
            {
             signal(45,handle);
             /*printf("%d:%d\n",SIG_IGN,SIG_DFL);*/
             /*signal(SIGINT,SIG_IGN);*/
             while(1){
              /*printf("Hello信號!\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:時間顯示*/
                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ā)送信號:可靠信號>=34*/
               kill(pid_code,34);
              }
              /*退出整個任務(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 大龍 閱讀(743) 評論(0)  編輯 收藏 引用


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


            91超碰碰碰碰久久久久久综合| 亚洲AV无码1区2区久久| 狠狠色丁香久久婷婷综合| 久久精品国产亚洲一区二区| 国产精品99久久免费观看| 97久久久精品综合88久久| 欧美综合天天夜夜久久| 亚洲狠狠久久综合一区77777| 91精品国产高清久久久久久国产嫩草| 91精品国产91久久综合| 狠狠色综合久久久久尤物| 久久国产精品免费| 免费无码国产欧美久久18| 欧美成a人片免费看久久| 色综合久久88色综合天天 | 久久午夜免费视频| 久久精品aⅴ无码中文字字幕重口| 国产成人精品久久一区二区三区| 成人午夜精品久久久久久久小说| 久久久久综合中文字幕| 久久久久亚洲av成人网人人软件| 97久久精品国产精品青草| 久久伊人影视| 99国产精品久久| 亚洲欧美日韩精品久久亚洲区| 久久国产精品无码一区二区三区| 99久久国产热无码精品免费久久久久| 区亚洲欧美一级久久精品亚洲精品成人网久久久久| 久久无码专区国产精品发布| 99久久国语露脸精品国产| 亚洲国产精品无码久久久久久曰| 成人久久久观看免费毛片| 中文精品99久久国产| 国产—久久香蕉国产线看观看| 久久99九九国产免费看小说| 国产精品成人久久久久久久| 久久久久久国产精品无码超碰| 久久99热这里只有精品66| 久久久久久极精品久久久| AV无码久久久久不卡网站下载| 久久午夜夜伦鲁鲁片免费无码影视 |