自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux驅(qū)動(dòng)技術(shù)(一) _內(nèi)存申請(qǐng)

系統(tǒng) Linux 系統(tǒng)運(yùn)維
內(nèi)核程序也需要?jiǎng)討B(tài)的分配內(nèi)存,不同的是,內(nèi)核進(jìn)程可以控制分配的內(nèi)存是在用戶空間還是內(nèi)核空間,前者可以用于給用戶空間的堆區(qū)分配內(nèi)存,eg,用戶進(jìn)程的用戶空間的malloc最終就會(huì)通過(guò)系統(tǒng)調(diào)用回調(diào)內(nèi)核空間的內(nèi)存分配函數(shù),此時(shí)該內(nèi)存分配函數(shù)就屬于該用戶進(jìn)程,可以給在該用戶進(jìn)程的堆區(qū)分配空間并返回,最終使得一個(gè)用會(huì)進(jìn)程在自己的用戶空間獲得內(nèi)存分配;后者只在內(nèi)核空間分配,所以用戶進(jìn)程不能直接訪問(wèn)該空間,所以多用在滿足內(nèi)核程序自身的內(nèi)存需求。

先上基礎(chǔ),下圖是Linux的內(nèi)存映射模型

  • 每一個(gè)進(jìn)程都有自己的進(jìn)程空間,進(jìn)程空間的0-3G是用戶空間,3G-4G是內(nèi)核空間
  • 每個(gè)進(jìn)程的用戶空間不在同一個(gè)物理內(nèi)存頁(yè),但是所有的進(jìn)程的內(nèi)核空間對(duì)應(yīng)同樣的物理地址
  • vmalloc分配的地址可以高端內(nèi)存,也可以是低端內(nèi)存
  • 0-896MB的物理地址是線性映射到物理映射區(qū)的。  

Linux的內(nèi)存映射模型 

內(nèi)存動(dòng)態(tài)申請(qǐng)

和應(yīng)用層一樣,內(nèi)核程序也需要?jiǎng)討B(tài)的分配內(nèi)存,不同的是,內(nèi)核進(jìn)程可以控制分配的內(nèi)存是在用戶空間還是內(nèi)核空間,前者可以用于給用戶空間的堆區(qū)分配內(nèi)存,eg,用戶進(jìn)程的用戶空間的malloc最終就會(huì)通過(guò)系統(tǒng)調(diào)用回調(diào)內(nèi)核空間的內(nèi)存分配函數(shù),此時(shí)該內(nèi)存分配函數(shù)就屬于該用戶進(jìn)程,可以給在該用戶進(jìn)程的堆區(qū)分配空間并返回,最終使得一個(gè)用會(huì)進(jìn)程在自己的用戶空間獲得內(nèi)存分配;后者只在內(nèi)核空間分配,所以用戶進(jìn)程不能直接訪問(wèn)該空間,所以多用在滿足內(nèi)核程序自身的內(nèi)存需求,下面是Linux內(nèi)核空間申請(qǐng)內(nèi)存常用API:

kmalloc - kfree

kmalloc申請(qǐng)的內(nèi)存在物理內(nèi)存上是連續(xù)的,他們與真實(shí)的物理地址只有一個(gè)固定的偏移,因此存在簡(jiǎn)單的轉(zhuǎn)換關(guān)系。這個(gè)API 多用來(lái)申請(qǐng)不到一個(gè)page大小的內(nèi)存。kmalloc的底層需要調(diào)用__get_free_pages,參數(shù)中表示內(nèi)存類型的gtp_t flags正是這個(gè)函數(shù)的縮寫(xiě),常用的內(nèi)存類型有GFP_USER,GFP_KERNEL,GFP_ATOMIC幾種。

  • GFP_USER表示為用戶空間頁(yè)分配內(nèi)存,可以阻塞;
  • GFP_KERNEL是最常用的flag,注意,使用這個(gè)flag來(lái)申請(qǐng)內(nèi)存時(shí),如果暫時(shí)不能滿足,會(huì)引起進(jìn)程阻塞,So,一定不要在中斷處理函數(shù),tasklet和內(nèi)核定時(shí)器等非進(jìn)程上下文中使用GFP_KERNEL!!!
  • GFP_ATOMIC就可以用于上述三種情境,這個(gè)flag表示如果申請(qǐng)的內(nèi)存不能用,則立即返回。
  1. /** 
  2.  * kmalloc - allocate memory 
  3.  * @size: how many bytes of memory are required. 
  4.  * @flags: the type of memory to allocate. 
  5.  * The @flags argument may be one of
  6.  * %GFP_USER - Allocate memory on behalf of user.  May sleep. 
  7.  * %GFP_KERNEL - Allocate normal kernel ram.  May sleep. 
  8.  * %GFP_ATOMIC - Allocation will not sleep.  May use emergency pools. 
  9.  *  
  10.  * For example, use this inside interrupt handlers. 
  11.  */ 
  12. void *kmalloc(size_t size, gfp_t flags); 
  13. /** 
  14.  * kfree - free previously allocated memory 
  15.  * @objp: pointer returned by kmalloc. 
  16.  * If @objp is NULLno operation is performed. 
  17.  */ 
  18. void kfree(const void *objp);  

同系列API還有

  1. void *kzalloc(size_t size, gfp_t flags)     

__get_free_pages - free_pages

__get_free_pages()與kmalloc()一樣是物理連續(xù)的內(nèi)存,這一系列函數(shù)是Linux內(nèi)核中***層的用于獲取空閑內(nèi)存的方法,因?yàn)榈讓拥腷uddy算法都是以(2^n)×PAGE_SIZE來(lái)管理內(nèi)存的,所以他們總是以頁(yè)為單位分配內(nèi)存的

  1. unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)  void free_pages(unsigned long addr, unsigned int order)  

同系列API還有

  1. unsigned long __get_free_page(gfp_t gfp)        unsigned long get_zeroed_page(gfp_t gfp_mask)    struct page *alloc_pages(gfp_t gfp_mask, unsigned int order
  1. void free_page(unsigned long addr) 

vmalloc - vfree

vmalloc在虛擬內(nèi)存空間給出一塊連續(xù)的內(nèi)存區(qū),實(shí)質(zhì)上,這片連續(xù)的虛擬內(nèi)存在物理內(nèi)存中并不一定連續(xù),所以vmalloc申請(qǐng)的虛擬內(nèi)存和物理內(nèi)存之間也就沒(méi)有簡(jiǎn)單的換算關(guān)系,正因如此,vmalloc()通常用于分配遠(yuǎn)大于__get_free_pages()的內(nèi)存空間,它的實(shí)現(xiàn)需要建立新的頁(yè)表,此外還會(huì)調(diào)用使用GFP_KERN的kmalloc,so,一定不要在中斷處理函數(shù),tasklet和內(nèi)核定時(shí)器等非進(jìn)程上下文中使用vmalloc!

  1. /**      
  2.  * vmalloc  -  allocate virtually contiguous memory 
  3.  * @size:          allocation size 
  4.  * Allocate enough pages to cover @size from the page level allocator and map them into contiguous kernel virtual space
  5.  */void *vmalloc(unsigned long size)   /** 
  6.  *      vfree  -  release memory allocated by vmalloc() 
  7.  *      @addr:          memory base address 
  8.  */void vfree(const void *addr)   

同系列的API還有

  1. /** 
  2.  * vmalloc_32  -  allocate virtually contiguous memory (32bit addressable) 
  3.  * @size:          allocation size 
  4.  * Allocate enough 32bit PA addressable pages to cover @size from the page level allocator and map them into contiguous kernel virtual space
  5.  */void *vmalloc_32(unsigned long size)   

slab緩存

我們知道,頁(yè)是內(nèi)存映射的基本單位,但內(nèi)核中很多頻繁創(chuàng)建的對(duì)象所需內(nèi)存都不到一頁(yè),此時(shí)如果仍然按照頁(yè)映射的方式,頻繁的進(jìn)行分配和釋放就會(huì)造成資源的浪費(fèi),同時(shí)也會(huì)降低系統(tǒng)性能。為了解決的這樣的問(wèn)題,內(nèi)核引入了slab機(jī)制,使對(duì)象在前后兩次被使用時(shí)被分配在同一塊內(nèi)存或同一類內(nèi)存空間,且保留了基本的數(shù)據(jù)結(jié)構(gòu),就可以大大提高效率。kmalloc的底層即是使用slab算法管理分配的內(nèi)存的。注意,slab依然是以頁(yè)為單位進(jìn)行映射,只是映射之后分割這些頁(yè)為相同的更小的單元,從而節(jié)省了內(nèi)存。slab分配的單元不能小于32B或大于128K。

  1. /** 
  2.  * kmem_cache_create - 創(chuàng)建slab緩存對(duì)象 
  3.  * @name:slab緩存區(qū)名字, 
  4.  * @size:slab分配的緩存區(qū)的每一個(gè)單元的大小 
  5.  * @align:緩存區(qū)內(nèi)存的對(duì)齊方式,一般給0 
  6.  * @flags:控制分配的位掩碼, 
  7.  * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) to catch references to uninitialised memory. 
  8.  * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check for buffer overruns. 
  9.  * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware cacheline.  This can be beneficial if you're counting cycles as closely as davem. 
  10.  * %SLAB_CACHE_DMA - Use GFP_DMA memory 
  11.  * %SLAB_STORE_USER - Store the last owner for bug hunting 
  12.  *define SLAB_PANIC - Panic if kmem_cache_create() fails  
  13.  */struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,unsigned long flags, void (*ctor)(void *))/** 
  14.  * kmem_cache_alloc - Allocate an object from this cache.  
  15.  * @cachep: The cache to allocate from
  16.  * @flags: See kmalloc(). 
  17.  * The flags are only relevant if the cache has no available objects. 
  18.  */void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)  /** 
  19.  * kmem_cache_free - Deallocate an object 
  20.  * @cachep: The cache the allocation was from
  21.  * @objp: The previously allocated object. 
  22.  * Free an object which was previously allocated from this cache. 
  23.  */void kmem_cache_free(struct kmem_cache *cachep, void *objp)  void kmem_cache_destroy(struct kmem_cache *s)   

范例

  1. //創(chuàng)建slab對(duì)象 
  2.  
  3. struct kmem_cache_t *xj_sbcache; 
  4. xj_sbcache = kmem_cache_create("xjslab",sizeof(struct xj_unit_t),0,SLAB_CACHE_DMA|SLAB_PANIC,NULL,NULL);//分配slab緩存 
  5.  
  6. struct xj_unit_t *xj_unit; 
  7. xj_unit = kmem_cache_alloc(xj_sbcache,GFP_KERNEL); 
  8. /* 使用slab緩存 */ 
  9. /* 釋放slab緩存 */ 
  10.  
  11. kmem_cache_free(xj_sbcache, xj_unit); 
  12. /* 銷毀slab緩存 */ 
  13.  
  14. kmem_cache_destroy(xj_sbcache);  

內(nèi)存池

除了slab機(jī)制,內(nèi)核還提供了傳統(tǒng)的內(nèi)存池機(jī)制來(lái)管理小塊內(nèi)存的分配。內(nèi)存池主要是用來(lái)解決可能出現(xiàn)的內(nèi)存不足的情況,因?yàn)橐粋€(gè)內(nèi)存池在創(chuàng)建的時(shí)候就已經(jīng)分配好了一內(nèi)存,當(dāng)我們用mempool_alloc向一個(gè)已經(jīng)創(chuàng)建好的內(nèi)存池申請(qǐng)申請(qǐng)內(nèi)存時(shí),該函數(shù)首先會(huì)嘗試回調(diào)內(nèi)存池創(chuàng)建時(shí)的分配內(nèi)存函數(shù),如果已經(jīng)沒(méi)有內(nèi)存可以分配,他就會(huì)使用內(nèi)存池創(chuàng)建時(shí)預(yù)先分配的內(nèi)存,這樣就可以避免因?yàn)闊o(wú)內(nèi)存分配而陷入休眠,當(dāng)然,如果預(yù)分配的內(nèi)存也已經(jīng)使用完畢,還是會(huì)陷入休眠。slab機(jī)制的目的是提高內(nèi)存使用率以及內(nèi)存管理效率,內(nèi)存池的目的是避免內(nèi)存的分配失敗。下面是內(nèi)核中提供的關(guān)于內(nèi)存池的API 

  1. /**      
  2.  * mempool_create - create a memory pool 
  3.  * @min_nr:    the minimum number of elements guaranteed to be  allocated for this pool. 
  4.  * @alloc_fn:  user-defined element-allocation function
  5.  * @free_fn:   user-defined element-freeing function
  6.  * @pool_data: optional private data available to the user-defined functions. 
  7.  *               
  8.  * this function creates and allocates a guaranteed size, preallocated memory pool. The pool can be used from the mempool_alloc() and mempool_free() functions.  
  9.  * This function might sleep. Both the alloc_fn() and the free_fn() functions might sleep - as long as the mempool_alloc() function is not called from IRQ contexts. 
  10.  */ 
  11. mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, mempool_free_t *free_fn, void *pool_data) 
  12.  
  13. /**      
  14.  * mempool_alloc - allocate an element from a specific memory pool 
  15.  * @pool:pointer to the memory pool which was allocated via mempool_create(). 
  16.  * @gfp_mask:  the usual allocation bitmask. 
  17.  * this function only sleeps if the alloc_fn() function sleeps or returns NULL. Note that due to preallocation, this function never* fails when called from process contexts. (it might fail if called from an IRQ context.) 
  18.  */      
  19. void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask)     
  20.  
  21. /** 
  22.  * mempool_free - return an element to the pool. 
  23.  * @element:   pool element pointer. 
  24.  * @pool:pointer to the memory pool which was allocated via mempool_create(). 
  25.  * 
  26.  * this function only sleeps if the free_fn() function sleeps. 
  27.  */      
  28. void mempool_free(void *element, mempool_t *pool)     
  29.  
  30. /** 
  31.  * mempool_destroy - deallocate a memory pool 
  32.  * @pool:pointer to the memory pool which was allocated via mempool_create(). 
  33.  * 
  34.  * Free all reserved elements in @pool and @pool itself.  This function only sleeps if the free_fn() function sleeps. 
  35.  */      
  36. void mempool_destroy(mempool_t *pool)   

 

責(zé)任編輯:龐桂玉 來(lái)源: 嵌入式Linux中文站
相關(guān)推薦

2017-03-01 12:36:15

Linux驅(qū)動(dòng)技術(shù)內(nèi)存

2022-07-10 20:47:39

linux中虛擬內(nèi)存

2017-02-28 17:46:15

Linux驅(qū)動(dòng)技術(shù)并發(fā)控制

2019-03-20 14:29:46

Linux虛擬內(nèi)存

2017-03-01 14:46:53

Linux驅(qū)動(dòng)技術(shù)異步通知技術(shù)

2017-03-01 13:06:39

Linux驅(qū)動(dòng)技術(shù)DMA編程

2022-05-10 08:49:46

設(shè)備驅(qū)動(dòng)Linux

2017-03-01 16:40:12

Linux驅(qū)動(dòng)技術(shù)設(shè)備阻塞

2021-04-12 12:00:13

Linux運(yùn)維Linux系統(tǒng)

2020-06-28 09:30:37

Linux內(nèi)存操作系統(tǒng)

2012-09-29 09:00:25

2021-11-12 11:28:01

Linux 內(nèi)核驅(qū)動(dòng)Linux 系統(tǒng)

2012-05-28 15:49:06

Linux凱迪拉克

2025-01-02 11:06:22

2021-01-18 08:23:23

內(nèi)存時(shí)底層CPU

2012-01-11 11:07:04

JavaJVM

2021-05-12 18:22:36

Linux 內(nèi)存管理

2021-11-22 08:14:23

Linux Linux驅(qū)動(dòng)Linux 系統(tǒng)

2018-10-10 14:14:51

Linux內(nèi)存映射

2022-07-28 08:00:00

Buddy算法內(nèi)存系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)