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

            大龍的博客

            常用鏈接

            統計

            最新評論

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

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

            案例:
              利用sigsuspend控制進程.
            作業:
              1.實現搖獎。
                要求:時間顯示使用SIALRM信號。
                控制:使用sigsuspend控制隨機數進程。

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

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

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

            void handle(int s){
             printf("信號發生.....\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()
            {
             /*變量區*/
             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){
                /*子進程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){
                /*子進程2:隨機數顯示*/
                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);
               }
              }   
             }
             /*主進程:鍵盤輸入*/
             int ch;
             while(1){
              ch=getch();
              if(ch=='\n'){
               /*停止隨機數進程*/
               /*發送信號:可靠信號>=34*/
               kill(pid_code,34);
              }
              /*退出整個任務*/
              if(ch=='x' || ch=='X'){
               /*通知子進程結束*/   
               sched_yield();
               break;
              }
             }
             wait(0);
             wait(0);
             delwin(wtime);
             delwin(wcode);
             endwin();
             exit(0); 
            }

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

            美女写真久久影院| 久久国产成人精品麻豆| 久久久久久国产精品免费免费| 久久国产精品成人免费| 久久久久久国产精品无码下载| 亚洲精品国产自在久久| 久久国产精品无码一区二区三区| 亚洲欧美精品伊人久久| 久久久久久精品无码人妻| 91久久精品国产免费直播| 久久亚洲精品无码VA大香大香| 国产亚洲美女精品久久久久狼| 久久伊人中文无码| 久久香蕉一级毛片| 久久精品国产久精国产果冻传媒 | 一本色道久久88—综合亚洲精品| 国内精品久久人妻互换| 久久天天躁狠狠躁夜夜躁2014| 精品久久久久久99人妻| 久久久亚洲欧洲日产国码二区| 午夜肉伦伦影院久久精品免费看国产一区二区三区| 香蕉久久久久久狠狠色| 国产午夜精品久久久久九九电影| 亚洲精品乱码久久久久久蜜桃不卡 | 色综合久久无码五十路人妻| 精品久久久久久久中文字幕 | 一本久久知道综合久久| 久久青青草原精品国产不卡| 品成人欧美大片久久国产欧美... 品成人欧美大片久久国产欧美 | 亚洲精品午夜国产va久久| 国产成人久久久精品二区三区| 欧美久久综合性欧美| 精品一区二区久久| 热久久国产精品| 一本伊大人香蕉久久网手机| 亚洲国产精品久久久久久| 国内精品久久久久国产盗摄| 精品视频久久久久| 麻豆久久久9性大片| 精品国产青草久久久久福利| 日韩AV无码久久一区二区|