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

            jake1036

            linux0.11信號處理之 exit.c

                                                                        exit.c 程序解析

             1 功能描述
               

                   該程序主要的作用是終止和退出的有關事宜。主要包括進程釋放、會話終止和程序退出處理函數以及殺死進程,終止進程,掛起進程調用函數。還包括進程信號發送函數,以及通知父進程子進程終止的函數tell_father()。
               釋放進程的函數release() 主要根據制定的任務數據結構指針,在任務數組中刪除指定的進程指針、釋放內存頁,并立刻讓內核重新調度任務的運行。
             

               kill_session() 函數通過向會話號與當前進程相同的進程發送掛斷進程的信號。

               sys_kill()用于向進程發送任何指定的信號。根據pid的不同參數值,該系統會向不同的進程發送任何指定的信號。

               do_exit() 函數是在exit系統調用的中斷處理程序中被調用。它首先會釋放當前進程的內存頁面。如果當前進程有子進程,就將子進程的father置為1 ,即把子進程的父進程變為進程1(init進程)。如果該子進程已經處于僵死的狀態,那么向進程1發送子進程終止信號SIGCHLD 。接著關閉當前進程打開的所有文件,釋放試驗的中斷設備。
               協處理器設備,若當前進程是進程組的領頭進程,則還需要終止所有相關進程。 隨后把當前進程置位僵死狀態,設置退出碼,并向父進程發送子進程終止信號SIGCHLD。最后讓內核重新調度任務運行。

            2  代碼示例
              
            #include <errno.h>
            #include 
            <signal.h>
            #include 
            <sys/wait.h>
            #include 
            <linux/sched.h>
            #include 
            <linux/kernel.h>
            #include 
            <linux/tty.h>
            #include 
            <asm/segment.h>

            int sys_pause(void) ; //把進程置為睡眠狀態
            int sys_close(int fd) ;//關閉指定文件的系統調用


            //釋放指定進程所占用的任務槽,及其任務數據結構占用的內存頁面

            void release(struct task_struct * p)
            {
              
            int i ;
              
            if(!p)
                
            return ;

              
            for(i = 1 ; i < NR_TASKS ; i++)   
              
            {
                
            if(task[i] == p)   
                 
            {
                    task[i] 
            = NULL;        
                    free_page((
            long)p) ;
                    schedule() ;    
            //重新調度進程 
                    return ; 
                 }

              }

               panic(
            "trying to release non - existent task");
            }


             
            //向指定的任務發送信號
             static inline int send_sig(long sig , struct task_struct * p , int priv)
             
            {
                
            if(!|| sig < 1 || sig > 32)
                   
            return -EINVAL ;
                
            if(priv || (current->euid == p->euid)|| suser())  //euid表示當前進程的權限
                  p->signal |= (1<<(sig - 1)) ;
                
            else
                  
            return -EPERM ;
                
            return 0 ;
             }


             
            //終止會話session
             static void kill_session(void)
             
            {
               
            struct task_struct **= NR_TASKS + task ;  //*p首先指向最后一個任務
               
            //掃描任務指針數組,如果所有的任務的會話號等于當前進程的會話號,那么就向它發送終止信號
               for(;p >= &FIRST_TASK ; p--
                
            {
                   
            if(*&& (*p)->session == current->session)
                     (
            *p)->signal |= 1 <<(SIGHUP - 1) ;
                }



             }

              
            //向進程組發送信號
            //這個函數用來向任何進程發送信號
            int sys_kill(int pid , int sig)
            {
              
            struct task_struct **= NR_TASKS + task ;
              
            int err , retval = 0 ;
              
            if(!pid) while(--> &FIRST_TASK){   //如果當前進程pid==0。那么就會把信號發送給與當前進程在同一組中的進程
                if(*&& (*p)->pgrp == current->pid)  
                  
            if(err = send_sig(sig , *p , 1))  //強制發送
                     retval = err ; 
              }
             else if(pid > 0while(--> &FIRST_TASK){
                 
            if(*&& (*p)->pid == current->pid)  
                  
            if(err = send_sig(sig , *p , 0))  //強制發送
                     retval = err ; 
               }

             
            else if(pid == -1while(--> &FIRST_TASK){  
                  
            if(err = send_sig(sig , *p , 0))  //強制發送
                     retval = err ; 
               }
             
             
            else while(--> &FIRST_TASK)  
                
            if(*&& (*p)->pgrp == -pid)
                   
            if(err = send_sig(sig , *p , 0))  //強制發送
                     retval = err ; 
            }

              
             
            //通知父進程--向進程pid發送信號SIGCHLD ;默認情況下子進程將停止或者終止
             
            //如果沒有找到父進程,則自己釋放。

             
            static void tell_father(int pid)
             
            {
               
            int i ;
               
            if(pid)
                 
            //掃描進程數組表尋找指定進程pid,并向其發送子進程將停止或者終止信號
                 for(i = 0 ; i < NR_TASKS ; i++)
                 
            {
                   
            if(!task[i])
                      
            continue ;
                   
            if(task[i]->pid != pid)
                      
            continue ;
                   task[i]
            ->signal |= (1<<(SIGCHLD - 1)) ;
                   
            return ;  
                }

                 
            //如果沒有找到父進程,則進程就自己釋放。
                  printk("BAD BAD - no father found\b\r") ;
                  release(current) ;
             }

            //程序退出處理函數。在下面的sys_exit()函數中被調用
            int do_exit(long code)
            {
              
            int i ;
              free_page_tables(get_base(current
            ->ldt[1]) , get_limit(0x0f)) ;  
              free_page_tables(get_base(current
            ->ldt[2]) , get_limit(0x17)) ; 
              
            //如果當前進程有子進程,將子進程的father置為1。
              
            //若該子進程已經處于僵死狀態,則向進程1發送子進程終止信號SIGCHLD
              
            //如果該子進程已經處于僵死狀態,則向進程1發送子進程終止信號
              for(i = 0 ; i < NR_TASKS ; i++)  
                
            if(task[i] && task[i]->father == current->pid)
                 
            {
                   task[i]
            ->father = 1 ;
                   
            if(task[i]->state == TASK_ZOMBIE)    
                     (
            void)send_sig(SIGCHLD  , task[1] , 1) ;
                 }


               
            //關閉當前進程打開著的全部文件
               for(i = 0 ; i < NR_OPEN ;i++)   
                 
            if(current->filp[i])
                    sys_close(i) ;
               
            //對當前進程的工作目錄pwd,跟目錄root以及執行文件的i節點進行同步操作,放回各個i節點并分別置空
                iput(current->pwd) ;
                current
            ->pwd = NULL ;
                iput(current
            ->root) ;    
                current
            ->root = NULL ;
                iput(current
            ->executable) ;
                current
            ->executable = NULL ;
                
            //如果當前進程是會話頭領進程并且具有控制終端,則釋放該終端
                if(current->leader && current->tty >= 0)
                  tty_table[current
            ->tty].pgrp = 0 ;
                
            //如果當前進程上次使用過協處理器,則將last_task_used_math 置空
                if(last_task_used_math == current)
                  last_task_used_math 
            = NULL ;
                
            //如果當前進程是leader進程,則終止該會話的所有相關進程
                if(current->leader)
                  kill_session() ;

                
            //把當前進程的狀態變為僵死狀態,表明當前進程已經釋放了資源。并保存由父進程讀取的退出碼
                current->state = TASK_ZOMBIE ;
                current
            ->exit_code = code ;
                tell_father(current
            ->father) ;//通知父進程,子進程將結束
                schedule() ; //重新調度進程運行
                return (-1) ;
            }
             
             

             
            //系統調用exit()。終止進程
              int sys_exit(int error_code)
             
            {
               
            return do_exit((error_code & 0xff<< 8) ;   
             }

              

              
            //掛起當前進程,等待pid指定的子進程退出或者收到終止該進程的信號,或者是需要一個信號句柄
             int sys_waitpid(pid_t pid , unsigned long * stat_addr , int options)
             

                
            int flag , code ;  //flag標志作用于后面表示所選出的子進程處于就緒或者睡眠狀態
                struct task_struct ** p;
                verify_area(stat_addr , 
            4) ;
            repeat:
                flag 
            = 0 ;
                
            //從任務數組末端開始掃描所有的任務,跳過空項,本進程項以及非當前進程的子進程項
                for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
                 
            {  
                   
            if(!*|| *== current)  //跳過空項以及當前進程項
                     continue ;
                   
            if((*p)->father != current->pid)  //跳過非當前進程的子進程項
                     continue ;

                   
            //此時選擇到的進程一定是當前進程的子進程
                   
            //如果當前的pid>0,但是不等于參數pid
                   
            //就說明是當前進程其他的子進程
                   if(pid > 0)
                   
            {
                      
            if((*p)->pid != pid) 
                      
            {
                         
            continue ; 
                      }

                    }
             else if(!pid){  //如果pid==0,則表示正在等待組號等于當前進程的所有進程
                      if((*p)->pgrp != current->pgrp)
                        
            continue ; 
                    }
            else  if(pid != -1)//如果pid<-1
                      if((*p)->pgrp != -pid)
                        
            continue ;
                    }


                   
            //如果前3個對pid的判斷不符合標準,則表示當前進程正在等待其他任何子進程,即pid=-1的情況
                   
            //接下來根據子進程的狀態來處理
                   switch((*p)->state){
                      
            case TASK_STOPPED :          
                         
            if(!(options & WUNTRACED))
                          
            continue ;
                          put_fs_long(
            0x7f , stat_addr) ;
                          
            return (*p)->pid ;
                      
                      
            case TASK_ZOMBIE :  //如果子進程是僵死狀態,那么首先把子進程的用戶態時間和內核態時間加到當前進程中
                          current->cutime += (*p)->utime ;
                          current
            ->cstime += (*p)->stime ;
                          flag 
            = (*p)->pid ;   //臨時保存當前子進程的退出碼   
                          code = (*p)->exit_code ; //取當前進程的退出碼
                          release(*p) ; 
                          put_fs_long(code , stat_addr) ; 
            //置狀態信息為退出碼
                          return flag ; 
                       
            default :
                         flag 
            = 1 ;
                         
            continue ;

                   }

                 }

                 
                 
            if(flag){
                   
            if(options & WNOHANG)
                   
            {
                        
            return 0 ;
                   }

                   current
            ->state = TASK_INTERRUPTIBLE ; //置當前進程為可中斷狀態 
                   schedule() ;  //重新運行
                   if(!(current->signal &= ~(1<<(SIGCHLD-1)) ))     
                      
            goto repeat ;
                   
            else
                      
            return -EINTR ; 
               }


               
            return -ECHILD ;

             }



            posted on 2010-11-07 15:43 kahn 閱讀(1087) 評論(0)  編輯 收藏 引用

            一本大道加勒比久久综合| 热99RE久久精品这里都是精品免费| 狠狠综合久久综合88亚洲 | 久久99精品国产自在现线小黄鸭 | 久久777国产线看观看精品| 久久高清一级毛片| 少妇熟女久久综合网色欲| 久久九九青青国产精品| 香蕉久久久久久狠狠色| 久久综合久久综合久久| 久久精品国产亚洲AV不卡| 久久青草国产精品一区| 色偷偷久久一区二区三区| 久久久精品久久久久特色影视| 久久精品亚洲精品国产色婷| 色99久久久久高潮综合影院| 久久免费线看线看| 精品熟女少妇a∨免费久久| 久久这里都是精品| 久久久久国产成人精品亚洲午夜| 久久久无码一区二区三区 | 久久精品无码专区免费青青| 亚洲欧美精品一区久久中文字幕 | 性做久久久久久免费观看| 久久久久久综合一区中文字幕| 亚洲精品无码久久久影院相关影片| 久久高潮一级毛片免费| 国产叼嘿久久精品久久| 好久久免费视频高清| 久久婷婷成人综合色综合| 亚洲AV日韩精品久久久久久 | 久久午夜无码鲁丝片午夜精品| 国产精品99久久久久久人| 天天躁日日躁狠狠久久| 日产精品久久久久久久性色| 久久久久av无码免费网| 一本色道久久HEZYO无码| 亚洲AV乱码久久精品蜜桃| 色婷婷综合久久久中文字幕| 国产成人无码精品久久久性色| 久久久久久精品免费免费自慰|