<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      《Linux內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)》讀書筆記(十五)- 進(jìn)程地址空間(kernel 2.6.32.60)

      進(jìn)程地址空間也就是每個(gè)進(jìn)程所使用的內(nèi)存,內(nèi)核對(duì)進(jìn)程地址空間的管理,也就是對(duì)用戶態(tài)程序的內(nèi)存管理。

      主要內(nèi)容

      • 地址空間(mm_struct)
      • 虛擬內(nèi)存區(qū)域(VMA)
      • 地址空間和頁(yè)表

       

      1. 地址空間(mm_struct)

      地址空間就是每個(gè)進(jìn)程所能訪問(wèn)的內(nèi)存地址范圍。

      這個(gè)地址范圍不是真實(shí)的,是虛擬地址的范圍,有時(shí)甚至?xí)^(guò)實(shí)際物理內(nèi)存的大小。

       

      現(xiàn)代的操作系統(tǒng)中進(jìn)程都是在保護(hù)模式下運(yùn)行的,地址空間其實(shí)是操作系統(tǒng)給進(jìn)程用的一段連續(xù)的虛擬內(nèi)存空間。

      地址空間最終會(huì)通過(guò)頁(yè)表映射到物理內(nèi)存上,因?yàn)閮?nèi)核操作的是物理內(nèi)存。

       

      雖然地址空間的范圍很大,但是進(jìn)程也不一定有權(quán)限訪問(wèn)全部的地址空間(一般都是只能訪問(wèn)地址空間中的一些地址區(qū)間),

      進(jìn)程能夠訪問(wèn)的那些地址區(qū)間也稱為 內(nèi)存區(qū)域。

      進(jìn)程如果訪問(wèn)了有效內(nèi)存區(qū)域以外的內(nèi)容就會(huì)報(bào) “段錯(cuò)誤” 信息。

       

      內(nèi)存區(qū)域中主要包含以下信息:

      • - 代碼段(text section),即可執(zhí)行文件代碼的內(nèi)存映射
      • - 數(shù)據(jù)段(data section),即可執(zhí)行文件的已初始化全局變量的內(nèi)存映射
      • - bss段的零頁(yè)(頁(yè)面信息全是0值),即未初始化全局變量的內(nèi)存映射
      • - 進(jìn)程用戶空間棧的零頁(yè)內(nèi)存映射
      • - 進(jìn)程使用的C庫(kù)或者動(dòng)態(tài)鏈接庫(kù)等共享庫(kù)的代碼段,數(shù)據(jù)段和bss段的內(nèi)存映射
      • - 任何內(nèi)存映射文件
      • - 任何共享內(nèi)存段
      • - 任何匿名內(nèi)存映射,比如由 malloc() 分配的內(nèi)存

      bss是 block started by symbol 的縮寫。

       

      linux中內(nèi)存相關(guān)的概念稍微整理了一下,供參考:

      英文

      含義

      SIZE 進(jìn)程映射的內(nèi)存大小,這不是進(jìn)程實(shí)際使用的內(nèi)存大小
      RSS(Resident set size) 實(shí)際駐留在“內(nèi)存”中的內(nèi)存大小,不包含已經(jīng)交換出去的內(nèi)存
      SHARE RSS中與其他進(jìn)程共享的內(nèi)存大小
      VMSIZE 進(jìn)程占用的總地址空間,包含沒(méi)有映射到內(nèi)存中的頁(yè)
      Private RSS 僅由進(jìn)程單獨(dú)占用的RSS,也就是進(jìn)程實(shí)際占用的內(nèi)存

       

      1.1 mm_struct介紹

      linux中的地址空間是用 mm_struct 來(lái)表示的。

      下面對(duì)其中一些關(guān)鍵的屬性進(jìn)行了注釋,有些屬性我也不是很了解......

      struct mm_struct {
          struct vm_area_struct * mmap;        /* [內(nèi)存區(qū)域]鏈表 */
          struct rb_root mm_rb;               /* [內(nèi)存區(qū)域]紅黑樹(shù) */
          struct vm_area_struct * mmap_cache;    /* 最近一次訪問(wèn)的[內(nèi)存區(qū)域] */
          unsigned long (*get_unmapped_area) (struct file *filp,
                      unsigned long addr, unsigned long len,
                      unsigned long pgoff, unsigned long flags);  /* 獲取指定區(qū)間內(nèi)一個(gè)還未映射的地址,出錯(cuò)時(shí)返回錯(cuò)誤碼 */
          void (*unmap_area) (struct mm_struct *mm, unsigned long addr);  /* 取消地址 addr 的映射 */
          unsigned long mmap_base;        /* 地址空間中可以用來(lái)映射的首地址 */
          unsigned long task_size;        /* 進(jìn)程的虛擬地址空間大小 */
          unsigned long cached_hole_size;     /* 如果不空的話,就是 free_area_cache 后最大的空洞 */
          unsigned long free_area_cache;        /* 地址空間的第一個(gè)空洞 */
          pgd_t * pgd;                        /* 頁(yè)全局目錄 */
          atomic_t mm_users;            /* 使用地址空間的用戶數(shù) */
          atomic_t mm_count;            /* 實(shí)際使用地址空間的計(jì)數(shù), (users count as 1) */
          int map_count;                /* [內(nèi)存區(qū)域]個(gè)數(shù) */
          struct rw_semaphore mmap_sem;   /* 內(nèi)存區(qū)域信號(hào)量 */
          spinlock_t page_table_lock;        /* 頁(yè)表鎖 */
      
          struct list_head mmlist;        /* 所有地址空間形成的鏈表 */
      
          /* Special counters, in some configurations protected by the
           * page_table_lock, in other configurations by being atomic.
           */
          mm_counter_t _file_rss;
          mm_counter_t _anon_rss;
      
          unsigned long hiwater_rss;    /* High-watermark of RSS usage */
          unsigned long hiwater_vm;    /* High-water virtual memory usage */
      
          unsigned long total_vm, locked_vm, shared_vm, exec_vm;
          unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
          unsigned long start_code, end_code, start_data, end_data; /* 代碼段,數(shù)據(jù)段的開(kāi)始和結(jié)束地址 */
          unsigned long start_brk, brk, start_stack; /* 堆的首地址,尾地址,進(jìn)程棧首地址 */
          unsigned long arg_start, arg_end, env_start, env_end; /* 命令行參數(shù),環(huán)境變量首地址,尾地址 */
      
          unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
      
          struct linux_binfmt *binfmt;
      
          cpumask_t cpu_vm_mask;
      
          /* Architecture-specific MM context */
          mm_context_t context;
      
          /* Swap token stuff */
          /*
           * Last value of global fault stamp as seen by this process.
           * In other words, this value gives an indication of how long
           * it has been since this task got the token.
           * Look at mm/thrash.c
           */
          unsigned int faultstamp;
          unsigned int token_priority;
          unsigned int last_interval;
      
          unsigned long flags; /* Must use atomic bitops to access the bits */
      
          struct core_state *core_state; /* coredumping support */
      #ifdef CONFIG_AIO
          spinlock_t        ioctx_lock;
          struct hlist_head    ioctx_list;
      #endif
      #ifdef CONFIG_MM_OWNER
          /*
           * "owner" points to a task that is regarded as the canonical
           * user/owner of this mm. All of the following must be true in
           * order for it to be changed:
           *
           * current == mm->owner
           * current->mm != mm
           * new_owner->mm == mm
           * new_owner->alloc_lock is held
           */
          struct task_struct *owner;
      #endif
      
      #ifdef CONFIG_PROC_FS
          /* store ref to file /proc/<pid>/exe symlink points to */
          struct file *exe_file;
          unsigned long num_exe_file_vmas;
      #endif
      #ifdef CONFIG_MMU_NOTIFIER
          struct mmu_notifier_mm *mmu_notifier_mm;
      #endif
      };

      補(bǔ)充說(shuō)明1: 上面的屬性中,mm_users 和 mm_count 很容易混淆,這里特別說(shuō)明一下:(下面的內(nèi)容有網(wǎng)上查找的,也有我自己理解的)

      mm_users 比較好理解,就是 mm_struct 被用戶空間進(jìn)程(線程)引用的次數(shù)。

      如果進(jìn)程A中創(chuàng)建了3個(gè)新線程,那么 進(jìn)程A(這時(shí)候叫線程A也可以)對(duì)應(yīng)的 mm_struct 中的 mm_users = 4

       

      補(bǔ)充一點(diǎn),linux中進(jìn)程和線程幾乎沒(méi)有什么區(qū)別,就是看它是否共享進(jìn)程地址空間,共享進(jìn)程地址空間就是線程,反之就是進(jìn)程。

      所以,如果子進(jìn)程和父進(jìn)程共享了進(jìn)程地址空間,那么父子進(jìn)程都可以看做線程。如果父子進(jìn)程沒(méi)有共享進(jìn)程地址空間,就是2個(gè)進(jìn)程

       

      mm_count 則稍微有點(diǎn)繞人,其實(shí)它記錄就是 mm_struct 實(shí)際的引用計(jì)數(shù)。

      簡(jiǎn)單點(diǎn)說(shuō),當(dāng) mm_users=0 時(shí),并不一定能釋放此 mm_struct,只有當(dāng) mm_count=0 時(shí),才可以確定釋放此 mm_struct

       

      從上面的解釋可以看出,可能引用 mm_struct 的并不只是用戶空間的進(jìn)程(線程)

      當(dāng) mm_users>0 時(shí), mm_count 會(huì)增加1, 表示有用戶空間進(jìn)程(線程)在使用 mm_struct。不管使用 mm_struct 的用戶進(jìn)程(線程)有幾個(gè), mm_count 都只是增加1。

      也就是說(shuō),如果只有1個(gè)進(jìn)程使用 mm_struct,那么 mm_users=1,mm_count也是 1。

      如果有9個(gè)線程在使用 mm_struct,那么 mm_users=9,而 mm_count 仍然為 1。

       

      那么 mm_count 什么情況下會(huì)大于 1呢?

      當(dāng)有內(nèi)核線程使用 mm_struct 時(shí),mm_count 才會(huì)再增加 1。

      內(nèi)核線程為何會(huì)使用用戶空間的 mm_struct 是有其他原因的,這個(gè)后面再闡述。這里先知道內(nèi)核線程使用 mm_struct 時(shí)也會(huì)導(dǎo)致 mm_count 增加 1。

      在下面這種情況下,mm_count 就很有必要了:

      • - 進(jìn)程A啟動(dòng),并申請(qǐng)了一個(gè) mm_struct,此時(shí) mm_users=1, mm_count=1
      • - 進(jìn)程A中新建了2個(gè)線程,此時(shí) mm_users=3, mm_count=1
      • - 內(nèi)核調(diào)度發(fā)生,進(jìn)程A及相關(guān)線程都被掛起,一個(gè)內(nèi)核線程B 使用了進(jìn)程A 申請(qǐng)的 mm_struct,此時(shí) mm_users=3, mm_count=2
      • - CPU的另一個(gè)core調(diào)度了進(jìn)程A及其線程,并且執(zhí)行完了進(jìn)程A及其線程的所有操作,也就是進(jìn)程A退出了。此時(shí) mm_users=0, mm_count=1
      •   在這里就看出 mm_count 的用處了,如果只有 mm_users 的話,這里 mm_users=0 就會(huì)釋放 mm_struct,從而有可能導(dǎo)致 內(nèi)核線程B 異常。
      • - 內(nèi)核線程B 執(zhí)行完成后退出,這時(shí) mm_users=0,mm_count=0,可以安全釋放 mm_struct 了

       

      補(bǔ)充說(shuō)明2:為何內(nèi)核線程會(huì)使用用戶空間的 mm_struct?

      對(duì)Linux來(lái)說(shuō),用戶進(jìn)程和內(nèi)核線程都是task_struct的實(shí)例,

      唯一的區(qū)別是內(nèi)核線程是沒(méi)有進(jìn)程地址空間的(內(nèi)核線程使用的內(nèi)核地址空間),內(nèi)核線程的mm描述符是NULL,即內(nèi)核線程的tsk->mm域是空(NULL)。

      內(nèi)核調(diào)度程序在進(jìn)程上下文的時(shí)候,會(huì)根據(jù)tsk->mm判斷即將調(diào)度的進(jìn)程是用戶進(jìn)程還是內(nèi)核線程。

      但是雖然內(nèi)核線程不用訪問(wèn)用戶進(jìn)程地址空間,但是仍然需要頁(yè)表來(lái)訪問(wèn)內(nèi)核自己的空間。

      而任何用戶進(jìn)程來(lái)說(shuō),他們的內(nèi)核空間都是100%相同的,所以內(nèi)核會(huì)借用上一個(gè)被調(diào)用的用戶進(jìn)程的mm_struct中的頁(yè)表來(lái)訪問(wèn)內(nèi)核地址,這個(gè)mm_struct就記錄在active_mm。

       

      簡(jiǎn)而言之就是,對(duì)于內(nèi)核線程,tsk->mm == NULL表示自己內(nèi)核線程的身份,而tsk->active_mm是借用上一個(gè)用戶進(jìn)程的mm_struct,用mm_struct的頁(yè)表來(lái)訪問(wèn)內(nèi)核空間。

      對(duì)于用戶進(jìn)程,tsk->mm == tsk->active_mm。

       

      補(bǔ)充說(shuō)明3:除了 mm_users 和 mm_count 之外,還有 mmap 和 mm_rb 需要說(shuō)明以下:

      其實(shí) mmap 和 mm_rb 都是保存此 進(jìn)程地址空間中所有的內(nèi)存區(qū)域(VMA)的,前者是以鏈表形式存放,后者以紅黑樹(shù)形式存放。

      用2種數(shù)據(jù)結(jié)構(gòu)組織同一種數(shù)據(jù)是為了便于對(duì)VMA進(jìn)行高效的操作。

       

      1.2 mm_struct操作

      1. 分配進(jìn)程地址空間

      參考 kernel/fork.c 中的宏 allocate_mm

      #define allocate_mm()    (kmem_cache_alloc(mm_cachep, GFP_KERNEL))
      #define free_mm(mm)    (kmem_cache_free(mm_cachep, (mm)))

       

      其實(shí)分配進(jìn)程地址空間時(shí),都是從slab高速緩存中分配的,可以通過(guò) /proc/slabinfo 查看 mm_struct 的高速緩存

      # cat /proc/slabinfo | grep mm_struct
      mm_struct             35     45   1408    5    2 : tunables   24   12    8 : slabdata      9      9      0

       

      2. 撤銷進(jìn)程地址空間

      參考 kernel/exit.c 中的 exit_mm() 函數(shù)

      該函數(shù)會(huì)調(diào)用 mmput() 函數(shù)減少 mm_users 的值,

      當(dāng) mm_users=0 時(shí),調(diào)用 mmdropo() 函數(shù), 減少 mm_count 的值,

      如果 mm_count=0,那么調(diào)用 free_mm 宏,將 mm_struct 還給 slab高速緩存

       

      3. 查看進(jìn)程占用的內(nèi)存:

      cat /proc/<PID>/maps
      或者
      pmap PID

       

      2. 虛擬內(nèi)存區(qū)域(VMA)

      內(nèi)存區(qū)域在linux中也被稱為虛擬內(nèi)存區(qū)域(VMA),它其實(shí)就是進(jìn)程地址空間上一段連續(xù)的內(nèi)存范圍。

       

      2.1 VMA介紹

      VMA的定義也在 <linux/mm_types.h>

      struct vm_area_struct {
          struct mm_struct * vm_mm;    /* 相關(guān)的 mm_struct 結(jié)構(gòu)體 */
          unsigned long vm_start;        /* 內(nèi)存區(qū)域首地址 */
          unsigned long vm_end;        /* 內(nèi)存區(qū)域尾地址 */
      
          /* linked list of VM areas per task, sorted by address */
          struct vm_area_struct *vm_next, *vm_prev;  /* VMA鏈表 */
      
          pgprot_t vm_page_prot;        /* 訪問(wèn)控制權(quán)限 */
          unsigned long vm_flags;        /* 標(biāo)志 */
      
          struct rb_node vm_rb;       /* 樹(shù)上的VMA節(jié)點(diǎn) */
      
          /*
           * For areas with an address space and backing store,
           * linkage into the address_space->i_mmap prio tree, or
           * linkage to the list of like vmas hanging off its node, or
           * linkage of vma in the address_space->i_mmap_nonlinear list.
           */
          union {
              struct {
                  struct list_head list;
                  void *parent;    /* aligns with prio_tree_node parent */
                  struct vm_area_struct *head;
              } vm_set;
      
              struct raw_prio_tree_node prio_tree_node;
          } shared;
      
          /*
           * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
           * list, after a COW of one of the file pages.    A MAP_SHARED vma
           * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
           * or brk vma (with NULL file) can only be in an anon_vma list.
           */
          struct list_head anon_vma_node;    /* Serialized by anon_vma->lock */
          struct anon_vma *anon_vma;    /* Serialized by page_table_lock */
      
          /* Function pointers to deal with this struct. */
          const struct vm_operations_struct *vm_ops;
      
          /* Information about our backing store: */
          unsigned long vm_pgoff;        /* Offset (within vm_file) in PAGE_SIZE
                             units, *not* PAGE_CACHE_SIZE */
          struct file * vm_file;        /* File we map to (can be NULL). */
          void * vm_private_data;        /* was vm_pte (shared mem) */
          unsigned long vm_truncate_count;/* truncate_count or restart_addr */
      
      #ifndef CONFIG_MMU
          struct vm_region *vm_region;    /* NOMMU mapping region */
      #endif
      #ifdef CONFIG_NUMA
          struct mempolicy *vm_policy;    /* NUMA policy for the VMA */
      #endif
      };

       

      這個(gè)結(jié)構(gòu)體各個(gè)字段的英文注釋都比較詳細(xì),就不一一翻譯了。

      上述屬性中的 vm_flags 標(biāo)識(shí)了此VM 對(duì) VMA和頁(yè)面的影響:

      vm_flags 的宏定義參見(jiàn) <linux/mm.h>

      標(biāo)志

      對(duì)VMA及其頁(yè)面的影響

      VM_READ 頁(yè)面可讀取
      VM_WRITE 頁(yè)面可寫
      VM_EXEC 頁(yè)面可執(zhí)行
      VM_SHARED 頁(yè)面可共享
      VM_MAYREAD VM_READ 標(biāo)志可被設(shè)置
      VM_MAYWRITER VM_WRITE 標(biāo)志可被設(shè)置
      VM_MAYEXEC VM_EXEC 標(biāo)志可被設(shè)置
      VM_MAYSHARE VM_SHARE 標(biāo)志可被設(shè)置
      VM_GROWSDOWN 區(qū)域可向下增長(zhǎng)
      VM_GROWSUP 區(qū)域可向上增長(zhǎng)
      VM_SHM 區(qū)域可用作共享內(nèi)存
      VM_DENYWRITE 區(qū)域映射一個(gè)不可寫文件
      VM_EXECUTABLE 區(qū)域映射一個(gè)可執(zhí)行文件
      VM_LOCKED 區(qū)域中的頁(yè)面被鎖定
      VM_IO 區(qū)域映射設(shè)備I/O空間
      VM_SEQ_READ 頁(yè)面可能會(huì)被連續(xù)訪問(wèn)
      VM_RAND_READ 頁(yè)面可能會(huì)被隨機(jī)訪問(wèn)
      VM_DONTCOPY 區(qū)域不能在 fork() 時(shí)被拷貝
      VM_DONTEXPAND 區(qū)域不能通過(guò) mremap() 增加
      VM_RESERVED 區(qū)域不能被換出
      VM_ACCOUNT 該區(qū)域時(shí)一個(gè)記賬 VM 對(duì)象
      VM_HUGETLB 區(qū)域使用了 hugetlb 頁(yè)面
      VM_NONLINEAR 該區(qū)域是非線性映射的

       

      2.2 VMA操作

      vm_area_struct 結(jié)構(gòu)體定義中有個(gè) vm_ops 屬性,其中定義了內(nèi)核操作 VMA 的方法

      /*
       * These are the virtual MM functions - opening of an area, closing and
       * unmapping it (needed to keep files on disk up-to-date etc), pointer
       * to the functions called when a no-page or a wp-page exception occurs. 
       */
      struct vm_operations_struct {
          void (*open)(struct vm_area_struct * area);  /* 指定內(nèi)存區(qū)域加入到一個(gè)地址空間時(shí),該函數(shù)被調(diào)用 */
          void (*close)(struct vm_area_struct * area); /* 指定內(nèi)存區(qū)域從一個(gè)地址空間刪除時(shí),該函數(shù)被調(diào)用 */
          int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf); /* 當(dāng)沒(méi)有出現(xiàn)在物理頁(yè)面中的內(nèi)存被訪問(wèn)時(shí),該函數(shù)被調(diào)用 */
      
          /* 當(dāng)一個(gè)之前只讀的頁(yè)面變?yōu)榭蓪憰r(shí),該函數(shù)被調(diào)用,
           * 如果此函數(shù)出錯(cuò),將導(dǎo)致一個(gè) SIGBUS 信號(hào) */
          int (*page_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf);
      
          /* 當(dāng) get_user_pages() 調(diào)用失敗時(shí), 該函數(shù)被 access_process_vm() 函數(shù)調(diào)用 */
          int (*access)(struct vm_area_struct *vma, unsigned long addr,
                    void *buf, int len, int write);
      #ifdef CONFIG_NUMA
          /*
           * set_policy() op must add a reference to any non-NULL @new mempolicy
           * to hold the policy upon return.  Caller should pass NULL @new to
           * remove a policy and fall back to surrounding context--i.e. do not
           * install a MPOL_DEFAULT policy, nor the task or system default
           * mempolicy.
           */
          int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
      
          /*
           * get_policy() op must add reference [mpol_get()] to any policy at
           * (vma,addr) marked as MPOL_SHARED.  The shared policy infrastructure
           * in mm/mempolicy.c will do this automatically.
           * get_policy() must NOT add a ref if the policy at (vma,addr) is not
           * marked as MPOL_SHARED. vma policies are protected by the mmap_sem.
           * If no [shared/vma] mempolicy exists at the addr, get_policy() op
           * must return NULL--i.e., do not "fallback" to task or system default
           * policy.
           */
          struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
                          unsigned long addr);
          int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from,
              const nodemask_t *to, unsigned long flags);
      #endif
      };

      除了以上的操作之外,還有一些輔助函數(shù)來(lái)方便內(nèi)核操作內(nèi)存區(qū)域。

      這些輔助函數(shù)都可以在 <linux/mm.h> 中找到

      1. 查找地址空間

      /* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
      extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);
      extern struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr,
                               struct vm_area_struct **pprev);
      
      /* Look up the first VMA which intersects the interval start_addr..end_addr-1,
         NULL if none.  Assume start_addr < end_addr. */
      static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr)
      {
          struct vm_area_struct * vma = find_vma(mm,start_addr);
      
          if (vma && end_addr <= vma->vm_start)
              vma = NULL;
          return vma;
      }

       

      2. 創(chuàng)建地址區(qū)間

      static inline unsigned long do_mmap(struct file *file, unsigned long addr,
          unsigned long len, unsigned long prot,
          unsigned long flag, unsigned long offset)
      {
          unsigned long ret = -EINVAL;
          if ((offset + PAGE_ALIGN(len)) < offset)
              goto out;
          if (!(offset & ~PAGE_MASK))
              ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
      out:
          return ret;
      }

       

      3. 刪除地址區(qū)間

      extern int do_munmap(struct mm_struct *, unsigned long, size_t);

       

      3. 地址空間和頁(yè)表

      地址空間中的地址都是虛擬內(nèi)存中的地址,而CPU需要操作的是物理內(nèi)存,所以需要一個(gè)將虛擬地址映射到物理地址的機(jī)制。

      這個(gè)機(jī)制就是頁(yè)表,linux中使用3級(jí)頁(yè)面來(lái)完成虛擬地址到物理地址的轉(zhuǎn)換。

      1. PGD - 全局頁(yè)目錄,包含一個(gè) pgd_t 類型數(shù)組,多數(shù)體系結(jié)構(gòu)中 pgd_t 類型就是一個(gè)無(wú)符號(hào)長(zhǎng)整型

      2. PMD - 中間頁(yè)目錄,它是個(gè) pmd_t 類型數(shù)組

      3. PTE - 簡(jiǎn)稱頁(yè)表,包含一個(gè) pte_t 類型的頁(yè)表項(xiàng),該頁(yè)表項(xiàng)指向物理頁(yè)面

       

      虛擬地址 - 頁(yè)表 - 物理地址的關(guān)系如下圖:

      VM-PM

      posted @ 2013-10-04 16:28  wang_yb  閱讀(8928)  評(píng)論(1)    收藏  舉報(bào)
      主站蜘蛛池模板: 天堂影院一区二区三区四区| 2019亚洲午夜无码天堂| 日韩精品一区二区三区久| 国产精品久久无中文字幕| 久章草在线精品视频免费观看| 久久成人 久久鬼色| 強壮公弄得我次次高潮A片| 国产男女猛烈无遮挡免费视频网站 | 国产午夜精品福利在线观看| 人人澡人人妻人人爽人人蜜桃| 国产精品三级中文字幕| 欧产日产国产精品精品| 亚洲 欧洲 无码 在线观看| 亚洲男人第一无码av网站| 毛片av在线尤物一区二区| 猫咪社区免费资源在线观看| 伊人大杳焦在线| 国产微拍一区二区三区四区| 性色在线视频精品| 在线观看美女网站大全免费| 亚洲美免无码中文字幕在线| 卢氏县| 亚洲男人天堂一级黄色片| 天堂www在线中文| 亚洲乱码中文字幕小综合| 国产很色很黄很大爽的视频| 国产91丝袜在线观看| 欧美交a欧美精品喷水| 婷婷久久香蕉五月综合加勒比| 国产亚洲一区二区三区成人| 99国内精品久久久久久久| 精品日本免费一区二区三区| 国产色视频一区二区三区qq号| AV最新高清无码专区| 久久精品蜜芽亚洲国产av| 国产精品自偷一区在线观看| 福利无遮挡喷水高潮| 99久久精品国产综合一区| 一区二区和激情视频| 精品无码一区在线观看| 任我爽精品视频在线播放|