• <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信號(hào)處理之 exit.c

                                                                        exit.c 程序解析

             1 功能描述
               

                   該程序主要的作用是終止和退出的有關(guān)事宜。主要包括進(jìn)程釋放、會(huì)話終止和程序退出處理函數(shù)以及殺死進(jìn)程,終止進(jìn)程,掛起進(jìn)程調(diào)用函數(shù)。還包括進(jìn)程信號(hào)發(fā)送函數(shù),以及通知父進(jìn)程子進(jìn)程終止的函數(shù)tell_father()。
               釋放進(jìn)程的函數(shù)release() 主要根據(jù)制定的任務(wù)數(shù)據(jù)結(jié)構(gòu)指針,在任務(wù)數(shù)組中刪除指定的進(jìn)程指針、釋放內(nèi)存頁(yè),并立刻讓內(nèi)核重新調(diào)度任務(wù)的運(yùn)行。
             

               kill_session() 函數(shù)通過(guò)向會(huì)話號(hào)與當(dāng)前進(jìn)程相同的進(jìn)程發(fā)送掛斷進(jìn)程的信號(hào)。

               sys_kill()用于向進(jìn)程發(fā)送任何指定的信號(hào)。根據(jù)pid的不同參數(shù)值,該系統(tǒng)會(huì)向不同的進(jìn)程發(fā)送任何指定的信號(hào)。

               do_exit() 函數(shù)是在exit系統(tǒng)調(diào)用的中斷處理程序中被調(diào)用。它首先會(huì)釋放當(dāng)前進(jìn)程的內(nèi)存頁(yè)面。如果當(dāng)前進(jìn)程有子進(jìn)程,就將子進(jìn)程的father置為1 ,即把子進(jìn)程的父進(jìn)程變?yōu)檫M(jìn)程1(init進(jìn)程)。如果該子進(jìn)程已經(jīng)處于僵死的狀態(tài),那么向進(jìn)程1發(fā)送子進(jìn)程終止信號(hào)SIGCHLD 。接著關(guān)閉當(dāng)前進(jìn)程打開(kāi)的所有文件,釋放試驗(yàn)的中斷設(shè)備。
               協(xié)處理器設(shè)備,若當(dāng)前進(jìn)程是進(jìn)程組的領(lǐng)頭進(jìn)程,則還需要終止所有相關(guān)進(jìn)程。 隨后把當(dāng)前進(jìn)程置位僵死狀態(tài),設(shè)置退出碼,并向父進(jìn)程發(fā)送子進(jìn)程終止信號(hào)SIGCHLD。最后讓內(nèi)核重新調(diào)度任務(wù)運(yùn)行。

            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) ; //把進(jìn)程置為睡眠狀態(tài)
            int sys_close(int fd) ;//關(guān)閉指定文件的系統(tǒng)調(diào)用


            //釋放指定進(jìn)程所占用的任務(wù)槽,及其任務(wù)數(shù)據(jù)結(jié)構(gòu)占用的內(nèi)存頁(yè)面

            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() ;    
            //重新調(diào)度進(jìn)程 
                    return ; 
                 }

              }

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


             
            //向指定的任務(wù)發(fā)送信號(hào)
             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表示當(dāng)前進(jìn)程的權(quán)限
                  p->signal |= (1<<(sig - 1)) ;
                
            else
                  
            return -EPERM ;
                
            return 0 ;
             }


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



             }

              
            //向進(jìn)程組發(fā)送信號(hào)
            //這個(gè)函數(shù)用來(lái)向任何進(jìn)程發(fā)送信號(hào)
            int sys_kill(int pid , int sig)
            {
              
            struct task_struct **= NR_TASKS + task ;
              
            int err , retval = 0 ;
              
            if(!pid) while(--> &FIRST_TASK){   //如果當(dāng)前進(jìn)程pid==0。那么就會(huì)把信號(hào)發(fā)送給與當(dāng)前進(jìn)程在同一組中的進(jìn)程
                if(*&& (*p)->pgrp == current->pid)  
                  
            if(err = send_sig(sig , *p , 1))  //強(qiáng)制發(fā)送
                     retval = err ; 
              }
             else if(pid > 0while(--> &FIRST_TASK){
                 
            if(*&& (*p)->pid == current->pid)  
                  
            if(err = send_sig(sig , *p , 0))  //強(qiáng)制發(fā)送
                     retval = err ; 
               }

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

              
             
            //通知父進(jìn)程--向進(jìn)程pid發(fā)送信號(hào)SIGCHLD ;默認(rèn)情況下子進(jìn)程將停止或者終止
             
            //如果沒(méi)有找到父進(jìn)程,則自己釋放。

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

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

            //程序退出處理函數(shù)。在下面的sys_exit()函數(shù)中被調(diào)用
            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)) ; 
              
            //如果當(dāng)前進(jìn)程有子進(jìn)程,將子進(jìn)程的father置為1。
              
            //若該子進(jìn)程已經(jīng)處于僵死狀態(tài),則向進(jìn)程1發(fā)送子進(jìn)程終止信號(hào)SIGCHLD
              
            //如果該子進(jìn)程已經(jīng)處于僵死狀態(tài),則向進(jìn)程1發(fā)送子進(jìn)程終止信號(hào)
              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) ;
                 }


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

                
            //把當(dāng)前進(jìn)程的狀態(tài)變?yōu)榻┧罓顟B(tài),表明當(dāng)前進(jìn)程已經(jīng)釋放了資源。并保存由父進(jìn)程讀取的退出碼
                current->state = TASK_ZOMBIE ;
                current
            ->exit_code = code ;
                tell_father(current
            ->father) ;//通知父進(jìn)程,子進(jìn)程將結(jié)束
                schedule() ; //重新調(diào)度進(jìn)程運(yùn)行
                return (-1) ;
            }
             
             

             
            //系統(tǒng)調(diào)用exit()。終止進(jìn)程
              int sys_exit(int error_code)
             
            {
               
            return do_exit((error_code & 0xff<< 8) ;   
             }

              

              
            //掛起當(dāng)前進(jìn)程,等待pid指定的子進(jìn)程退出或者收到終止該進(jìn)程的信號(hào),或者是需要一個(gè)信號(hào)句柄
             int sys_waitpid(pid_t pid , unsigned long * stat_addr , int options)
             

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

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

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


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

                   }

                 }

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

                   current
            ->state = TASK_INTERRUPTIBLE ; //置當(dāng)前進(jìn)程為可中斷狀態(tài) 
                   schedule() ;  //重新運(yùn)行
                   if(!(current->signal &= ~(1<<(SIGCHLD-1)) ))     
                      
            goto repeat ;
                   
            else
                      
            return -EINTR ; 
               }


               
            return -ECHILD ;

             }



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


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


            久久精品国产福利国产琪琪| 亚洲精品成人网久久久久久| 亚洲乱码中文字幕久久孕妇黑人 | 久久受www免费人成_看片中文 | 久久偷看各类wc女厕嘘嘘| 国内精品伊人久久久久777| 2021精品国产综合久久| 亚洲国产成人久久精品99| 日韩精品久久久久久久电影蜜臀| a级毛片无码兔费真人久久| 久久久久久久久波多野高潮| 99久久精品免费看国产| 色欲综合久久中文字幕网| 国内精品久久久久久久涩爱| 久久久老熟女一区二区三区| 欧美精品福利视频一区二区三区久久久精品 | 久久久久久国产a免费观看黄色大片| 影音先锋女人AV鲁色资源网久久 | 久久国产亚洲精品| 久久国产视频99电影| 久久91亚洲人成电影网站| 久久人人爽人人爽人人AV| 性做久久久久久久久久久| 久久人人爽人爽人人爽av| 久久精品国产精品亚洲人人| 26uuu久久五月天| 青青青青久久精品国产| 久久精品a亚洲国产v高清不卡| 久久久久久久精品成人热色戒| 亚洲国产精品无码久久久久久曰| 99久久国产免费福利| 久久精品国产一区| 亚洲国产成人久久综合碰碰动漫3d | 亚洲AV无码久久| 中文字幕久久精品无码| 亚洲中文字幕无码久久精品1| 中文精品99久久国产| 久久国语露脸国产精品电影| 久久精品无码免费不卡| 久久人搡人人玩人妻精品首页| 蜜臀久久99精品久久久久久|