• <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---fork.c函數分析

            1 功能描述 
              fork()系統調用用于創建子進程,Linux中所有的進程都是進程0的子進程。

                copy_process()函數用于創建并復制進程代碼段和數據段以及環境,在進程復制的過程中,工作主要牽涉到進程數據結構中信息的設置。
                系統首先為新建進程在主內存區申請一頁內存來存放任務數據結構信息,并復制當前進程任務數據結構中的所有內容作為新進程任務數據結構的模板。
                隨后對已經復制的任務數據結構內容進行修改。把當前進程設置為新進程的父進程,清除信號位圖并復位新進程的各個統計值。接著根據當前進程環境設置新進程任務狀態段TSS中各個寄存器的值,新建進程內核態堆棧指針tss.esp0被設置成為任務數據結構所在內存頁面的頂端,而tss.ss0被設置為內核數據段選擇符。
              每當任務進入內核態運行的時候,其內核態堆棧指針初始位置不變,均為任務數據所在頁面的頂端。

             

             


              2源代碼分析

               
             #include <errno.h>
            #include 
            <linux/sched.h>
            #include 
            <linux/kernel.h>
            #include 
            <asm/segment.h>
            #include 
            <asm/system.h>

            extern void write_verify(unsigned long address) ;
            long last_pid = 0//最新進程號,其值會由get_empty_process生成
            void verify_area(void * addr ,  int size)
            {
               unsigned 
            long start ;
               start 
            = (unsigned long) addr ;
               size 
            += start & 0xfff ;
               start 
            &= 0xfffff000 ;
               start 
            += get_base(current->ldt[2]) ;
               
            while(size > 0){
                 size 
            -= 4096 ;  
                 write_verify(start) ;
                 start 
            += 4096 ;
               }

            }


            //該函數為新的進程在線性地址空間中設置新的代碼段和數據段基地址和限長
            int copy_mem(int nr , struct task_struct * p)
            {
               unsigned 
            long old_data_base , new_data_base , data_limit ;
               unsigned 
            long old_code_base , new_code_base , code_limit ;
               code_limit 
            = get_limit(0x0f) ;
               data_limit 
            = get_limit(0x17) ;
               old_code_base 
            = get_base(current->ldt[1]) ;
               old_data_base 
            = get_base(current->ldt[2]) ;
               
            if(old_code_base != old_data_base)
                 panic(
            "We donot support seperate ID") ;
               
            if(data_limit < code_limit) 
                 panic(
            "Bad data_limit") ;

               new_data_base 
            = new_code_base = nr * 0x4000000 ; //nr * 64MB
               p->start_code = new_code_base ;
               set_base(p
            ->ldt[1] , new_code_base) ;
               set_base(p
            ->ldt[2] , new_data_base) ;
               
            if(copy_page_tables(old_data_base , new_data_base , data_limit))
                
            {
                  free_page_tables(new_data_base , data_limit) ;
                  
            return -ENOMEM ;

                }

                
            return 0 ;   
            }


            //下面是主要的fork程序,負責復制系統進程信息
            //并且設置必要的寄存器,還整個地復制數據段

            int copy_process(int nr , long ebp , long edi , long esi , long gs , long none ,
             
            long ebx , long ecx , long edx , long fs , long es , long ds , long eip ,
            long cs , long eflags , long esp , long ss)
            {
              
            struct task_struct * p ;
              
            int i ;
              
            struct file * f ;
              p 
            = (struct task_struct *) get_free_page() ;
              
            if(!p)
                
            return -EAGAIN ;
              task[nr] 
            = p ;       
              
            *= * current ; //并不是指針的賦值 ,而是直接申請了一個空間 
              
            //下面開始修改任務數據結構的值
              p->state = TASK_UNINTERRUPTIBLE ; 
              p
            ->pid = last_pid ;
              p
            ->father = current->pid ;
              p
            ->counter = p->priority ;//設置時間片
              p->signal = 0 ;   //信號位圖置0
              p->alarm = 0 ; //報警定時器值
              p->leader = 0 ;//進程的領導權
              p->utime = p->stime = 0 ; //用戶態號和心態的運行時間
              p->cutime = p->cstime = 0 ;//子進程用戶態和和核心態的運行時間  
              p->start_time = jiffies ; //進程當前的運行時間
              

              p
            ->tss.back_link = 0  ;
              p
            ->tss.esp0 = PAGE_SIZE + (long) p ; //任務內核態棧指針
              p->tss.ss0 = 0x10 ;       //內核態的段選擇符,與數據段選擇符相同
              p->tss.eip = eip  ;
              p
            ->tss.eflags = eflags ; 
              p
            ->tss.eax = 0 ; //這是當fork()調用返回時 新進程會返回0的原因
              p->tss.ecx = ecx ;
              p
            ->tss.edx = edx ;
              p
            ->tss.ebx = ebx ; 
              p
            ->tss.esp = esp ;
              p
            ->tss.ebp = ebp ;
              p
            ->tss.esi = esi ;
              p
            ->tss.edi = edi ;
              p
            ->tss.es = es & 0xffff ;
              p
            ->tss.cs = cs & 0xffff ;
              p
            ->tss.ss = ss & 0xffff ;
              p
            ->tss.ds = ds & 0xffff ;
              p
            ->tss.fs = fs & 0xffff ;
              p
            ->tss.gs = gs & 0xffff ;
              p
            ->tss.ldt = _LDT(nr) ;  
              p
            ->tss.trace_bitmap = 0x80000000 ;
              

              
            if(last_task_used_math == current)
               __asm__(
            "clts ; fnsave %0" ::"m"(p->tss.i387)) ;
              
            //接下來復制進程頁表,即在線性地址空間設置新任務代碼段和數據段描述符中的基地址和限長,并復制頁表。  
              if(copy_mem(nr , p)){
                task[nr] 
            = NULL ;
                free_page((
            long)p) ;
                
            return -EAGAIN ;
              }


              
            //如果父進程中有些文件是打開的,則將對應文件的打開次數加1 ,因為子進程會共享父進程打開的這些文件
              for(i = 0 ; i < NR_OPEN ; i++)  
                
            if(f = p->filp[i])
                 f
            ->f_count++ ;
              
            if(current->pwd)
                 current
            ->pwd->i_count++ ;
              
            if(current->root)
                current
            ->root->i_count++ ;
              
            if(current->executable)
                current
            ->executable->i_count++ ;

              
            //最后在GDT表中設置新任務TSS段和LDT段描述符
              set_tss_desc(gdt + (nr<<1+ FIRST_TSS_ENTRY , &(p->tss)) ;
              set_ldt_desc(gdt 
            + (nr<<1+ FIRST_LDT_ENTRY , &(p->ldt)) ;
              p
            ->state = TASK_RUNNING ;  
               
              
            return last_pid ;
            }


            //為新進程取得不重復的進程號last_pid ,函數返回在任務數組中的任務號
             int find_empty_process(void)
            {
              
            int i ; 
              repeat:
                
            if((++last_pid) < 0) last_pid = 1 ;
                
            for(i = 0 ; i < NR_TASKS ; i++)
                   
            if(task[i] && task[i]->pid == last_pid)
                       
            goto repeat ;

                
            for(i = 1 ; i < NR_TASKS ; i++)  
                   
            if(!task[i])
                      
            return i ;

                
            return -EAGAIN ; 
            }










              

            posted on 2010-11-08 19:48 kahn 閱讀(1024) 評論(0)  編輯 收藏 引用

            无码8090精品久久一区| 99久久www免费人成精品| 久久久久亚洲AV无码专区首JN| 国产美女亚洲精品久久久综合| 国产精品成人久久久| 久久精品国产亚洲5555| 亚洲日韩欧美一区久久久久我| 热久久这里只有精品| 亚洲级αV无码毛片久久精品| 国产精品美女久久久久| 欧美日韩精品久久久免费观看| 久久久九九有精品国产| 久久综合亚洲色一区二区三区| 久久艹国产| 伊人久久大香线蕉综合5g| 99久久99久久精品国产片果冻| 9191精品国产免费久久| 色欲综合久久躁天天躁| 亚洲精品高清一二区久久| 久久久久久午夜精品| 波多野结衣AV无码久久一区| 国产成人综合久久久久久 | 精品久久久久久成人AV| 久久久久国产一级毛片高清板| 精品久久久无码21p发布| 99久久这里只有精品| 国产偷久久久精品专区| 久久精品国产精品亚洲| 一本大道久久a久久精品综合| 久久亚洲AV成人无码| 美女写真久久影院| 思思久久99热只有频精品66| 久久国产色AV免费观看| 久久无码国产专区精品| 精品无码久久久久久久动漫| 综合久久国产九一剧情麻豆| 久久综合狠狠综合久久97色| 2021久久精品国产99国产精品| 模特私拍国产精品久久| 国产精品对白刺激久久久| 久久亚洲AV无码西西人体|