slab 소스 코드 분석 - slab 초기 화 부터

35801 단어 Linux 커 널 분석
지난번 에 slab 의 주요 데이터 구 조 를 말 했 는데 이번 에는 초기 화 부터 소스 코드 분석 을 시작 합 니 다.
slab 의 초기 화 는 당연히 커 널 시작 부터 시작 되 었 습 니 다.커 널 시작 startkernel () 함수:
//        :)
asmlinkage void __init start_kernel(void)
{
    ...
    mem_init();    //       
    kmem_cache_init();    //slab    
    ...
}

그 중 kmem 호출cache_init () 함수, 이것 이 바로 slab 의 초기 화 입 니 다.
/*
 * Initialisation.  Called after the page allocator have been initialised and
 * before smp_init().
 */
 //             ,        kmalloc
void __init kmem_cache_init(void)
{
    size_t left_over;
    struct cache_sizes *sizes;
    struct cache_names *names;
    int i;
    int order;
    int node;

    //        1 ,            shared cache
    if (num_possible_nodes() == 1)  //              ,  #define num_possible_nodes() 1
        use_alien_caches = 0;             //  linux     

    // slab      ,    kmalloc               ,           
    // slab     ,   kmalloc            !!

    //    ,    initkem_list3         ,          
    //initkmem_list3       ,               
    for (i = 0; i < NUM_INIT_LISTS; i++) {       //FIXME: NUM_INIT_LIST      ,     2 * MAX_NODES+1 ?       3 * MAX_NODES
        kmem_list3_init(&initkmem_list3[i]);
        if (i < MAX_NUMNODES)
        //    cache_cache   slab cache     kmem_cache  ,   cache_cache  
        //           kmem_cache slab    
            cache_cache.nodelists[i] = NULL;
    }

    /*
     * Fragmentation resistance on low memory - only use bigger
     * page orders on machines with more than 32MB of memory.
     */
     //    slab_break_gfp_order   slab        ,      。
     //         : (1)          32MB,            ,BREAK_GFP_ORDER_HI      1,
     //      slab        ,        3   ,        8192K    (       4K,   4096);
     //(2)         32MB,  BREAK_GFP_ORDER_HI  0,           ,      ,      
    if (num_physpages > (32 << 20) >> PAGE_SHIFT)
        slab_break_gfp_order = BREAK_GFP_ORDER_HI;   //    slab     

    /* Bootstrap is tricky, because several objects are allocated
     * from caches that do not exist yet:
     * 1) initialize the cache_cache cache: it contains the struct
     *    kmem_cache structures of all caches, except cache_cache itself:
     *    cache_cache is statically allocated.
     *    Initially an __init data area is used for the head array and the
     *    kmem_list3 structures, it's replaced with a kmalloc allocated
     *    array at the end of the bootstrap.
     * 2) Create the first kmalloc cache.
     *    The struct kmem_cache for the new cache is allocated normally.
     *    An __init data area is used for the head array.
     * 3) Create the remaining kmalloc caches, with minimally sized
     *    head arrays.
     * 4) Replace the __init data head arrays for cache_cache and the first
     *    kmalloc cache with kmalloc allocated arrays.
     * 5) Replace the __init data for kmem_list3 for cache_cache and
     *    the other cache's with kmalloc allocated memory.
     * 6) Resize the head arrays of the kmalloc caches to their final sizes.
     */

    node = numa_node_id();   //    id,     0,        CPU  ,  0 

    /* 1) create the cache_cache */
    //   cache_chain   kmem_cache     
    INIT_LIST_HEAD(&cache_chain);
    list_add(&cache_cache.next, &cache_chain);
    //  cache         ,   L1      
    cache_cache.colour_off = cache_line_size(); //   L1       #define cache_line_size() L1_CACHE_BYTES
    //   cache_cache per-CPU cache,         kmalloc,             initarray_cache
    cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
    //   slab  ,     ,  CACHE_CACHE  0,   cache_cache           
    cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE];

    /*
     * struct kmem_cache size depends on nr_node_ids, which
     * can be less than MAX_NUMNODES.
     */
     //buffer_size           ,  cache_cache     kmem_cache      ,   buffer_size       kmem_cache    
     //           ,nodelists    kmem_cache   ,       ,    nodelists   UMA        ,    1 kmem_list3   
    cache_cache.buffer_size = offsetof(struct kmem_cache, nodelists) +
                 nr_node_ids * sizeof(struct kmem_list3 *);
#if 0 
#if DEBUG
    cache_cache.obj_size = cache_cache.buffer_size;
#endif
#endif

    //           buffer_size    ,       buffer_size                
    //        cache line         
    cache_cache.buffer_size = ALIGN(cache_cache.buffer_size,
                    cache_line_size());
    //         ,       slab    
    cache_cache.reciprocal_buffer_size =
        reciprocal_value(cache_cache.buffer_size);

    //  cache_cache       slab      ,order   slab   (PAGE_SIZEE<
    for (order = 0; order < MAX_ORDER; order++) { //#define MAX_ORDER 11

        cache_estimate(order, cache_cache.buffer_size,  //buffer_size   cache line   
            cache_line_size(), 0, &left_over, &cache_cache.num);  //  cache_cache     

        if (cache_cache.num) //num  0   struct kmem_cache      ,  ,         order   ,    gfporder
            break;
    }
    BUG_ON(!cache_cache.num);  //  

    cache_cache.gfporder = order;  //gfporder   slab  2^gfproder   ,         order    gfporder

    //colour_off          L1_CACHE_BYTES,       L1       ,                
    //           / L1       ,        colour    ,           ,   0
    cache_cache.colour = left_over / cache_cache.colour_off;   //     colour    ,    colour_off


    //  slab     kmem_bufctl_t              
    cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +  
                      sizeof(struct slab), cache_line_size());


    /* 2+3) create the kmalloc caches */
    sizes = malloc_sizes;   //malloc_sizes           
    names = cache_names;  //cache_name  cache 

    /*
     * Initialize the caches that provide memory for the array cache and the
     * kmem_list3 structures first.  Without this, further allocations will
     * bug.
     */
    //    struct array_cache   struct kmem_list3         general cache,             
    //INDEX_AC   local cache   struct arraycache_init   kmalloc size    ,          general cache,        cache local cache  
    sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name,
                    sizes[INDEX_AC].cs_size,
                    ARCH_KMALLOC_MINALIGN,
                    ARCH_KMALLOC_FLAGS|SLAB_PANIC,   //#define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN,        
                    NULL, NULL);

    if (INDEX_AC != INDEX_L3) {
    //  struct kmem_list3   struct arraycache_init   kmalloc size    ,          ,
    //   struct kmem_list3   cache,      cache
        sizes[INDEX_L3].cs_cachep =
            kmem_cache_create(names[INDEX_L3].name,
                sizes[INDEX_L3].cs_size,
                ARCH_KMALLOC_MINALIGN,
                ARCH_KMALLOC_FLAGS|SLAB_PANIC,
                NULL, NULL);
    }

    slab_early_init = 0;//             ,slab early init    ,    ,        slab

    //sizes->cs_size     malloc_sizes[0],     32  
    while (sizes->cs_size != ULONG_MAX) {  //    kmalloc         ,ULONG_MAX       ,
        /*
         * For performance, all the general caches are L1 aligned.
         * This should be particularly beneficial on SMP boxes, as it
         * eliminates(  ) "false sharing".
         * Note for systems short on memory removing the alignment will
         * allow tighter(  ) packing of the smaller caches.
         */
        if (!sizes->cs_cachep) {   
            sizes->cs_cachep = kmem_cache_create(names->name,
                    sizes->cs_size,
                    ARCH_KMALLOC_MINALIGN,
                    ARCH_KMALLOC_FLAGS|SLAB_PANIC,
                    NULL, NULL);
        }
#ifdef CONFIG_ZONE_DMA   //    DMA,     kmem_cache     ,  DMA,    
        sizes->cs_dmacachep = kmem_cache_create(
                    names->name_dma,
                    sizes->cs_size,
                    ARCH_KMALLOC_MINALIGN,
                    ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|
                        SLAB_PANIC,
                    NULL, NULL);
#endif
        sizes++;   //     ,  ++,      ,           general caches,   ULONG_MAX
        names++;
    }
    /* 4) Replace the bootstrap head arrays */
    {
        struct array_cache *ptr;

        //     arraycache     initarray_cache
        ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);  //GFP_KERNEL      

        //   
        local_irq_disable();
        BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
        memcpy(ptr, cpu_cache_get(&cache_cache),
               sizeof(struct arraycache_init));  // cache_cache per-cpu   array_cache   ptr
        /*
         * Do not assume that spinlocks can be initialized via memcpy:
         */
        spin_lock_init(&ptr->lock);

        cache_cache.array[smp_processor_id()] = ptr;  //     ptr?
        local_irq_enable();

        ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);

        local_irq_disable();
        BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)
               != &initarray_generic.cache);
        memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
               sizeof(struct arraycache_init));
        /*
         * Do not assume that spinlocks can be initialized via memcpy:
         */
        spin_lock_init(&ptr->lock);

        malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
            ptr;
        local_irq_enable();
    }
    /* 5) Replace the bootstrap kmem_list3's */
    {
        int nid;

        /* Replace the static kmem_list3 structures for the boot cpu */
        init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], node);

        for_each_online_node(nid) {
            init_list(malloc_sizes[INDEX_AC].cs_cachep,
                  &initkmem_list3[SIZE_AC + nid], nid);

            if (INDEX_AC != INDEX_L3) {
                init_list(malloc_sizes[INDEX_L3].cs_cachep,
                      &initkmem_list3[SIZE_L3 + nid], nid);
            }
        }
    }

    /* 6) resize the head arrays to their final sizes */
    {
        struct kmem_cache *cachep;
        mutex_lock(&cache_chain_mutex);
        list_for_each_entry(cachep, &cache_chain, next)
            if (enable_cpucache(cachep)) //          ,         
                BUG();
        mutex_unlock(&cache_chain_mutex);
    }

    /* Annotate slab for lockdep -- annotate the malloc caches */
    init_lock_keys();


    /* Done! */
    g_cpucache_up = FULL;

    /*
     * Register a cpu startup notifier callback that initializes
     * cpu_cache_get for all new cpus
     */
    register_cpu_notifier(&cpucache_notifier);

    /*
     * The reap timers are started later, with a module init call: That part
     * of the kernel is not yet operational.
     */
}

이 함수 가 바로 slab 초기 화의 주간 입 니 다.실행 절차:
  • initkmem 사용list 3 와 intarraycache 두 개의 정 지 량 에 수 동 으로 cache 를 채 웁 니 다.cache 의 다른 변수, cache 완성cache 초기 화.이것 은 kmem 을 캐 시 하 는 데 사 용 됩 니 다.cache 의, 버퍼 에 해당 하 는 버퍼:)
  • kmalloc 에 사용 할 다른 유 니 버 설 버퍼 만 들 기:
  • cache 의 이름과 크기 는 names [] 와 malloc 에 놓 여 있 습 니 다.sizes [] 두 배열 중 크기 에 대응 하 는 cache 는 malloc 에서sizes [] 에서 찾 을 수 있 습 니 다. 색인 은 대상 의 크기 를 분배 하 는 것 입 니 다.
  • 먼저 INDEX 만 들 기AC 와 INDEXL3 아래 에 표 시 된 cache (array cache 와 세 개의 체인, 크기 가 같 으 면 한 번 만 만 듭 니 다).
  • size 배열 의 각 크기 의 cache 를 순환 적 으로 만 듭 니 다.

  • 정적 로 컬 cache 전역 변 수 를 교체 합 니 다.
  • malloc 교체sizes[INDEX_AC].cs_cachep 의 local cache, 정적 변 수 를 가리 키 는 initarraycache.cache。
  • malloc 교체sizes[INDEX_AC].cx_cachep 의 local cache, 정적 변 수 를 가리 키 는 initarraygeneric.cache。 (kmem cache create () 에서 setup cpu cache () 함 수 를 호출 하면 정적 변 수 를 사용 합 니 다.
  • 정적 3 체인 교체:
  • cache cache 3 체인 을 교체 하고 정적 변 수 를 가리 키 는 initkmem list 3.
  • malloc sizes [INDEX AC]. cs cachep 3 체인 을 교체 합 니 다. 원래 정적 변수 initkmem list 3 를 가리 키 고 있 습 니 다.
  • 업데이트 초기 화 진도
  • 『 8194 』 정적 초기 화 된 구조: 예 를 들 어:
    /* internal cache of cache description objs */
    //                 
    static struct kmem_cache cache_cache = {
        .batchcount = 1,
        .limit = BOOT_CPUCACHE_ENTRIES,
        .shared = 1,
        .buffer_size = sizeof(struct kmem_cache),
        .name = "kmem_cache",  //  ,     kmem_cache
    };

    혹은
    static struct arraycache_init initarray_cache /*__initdata*/ =
        { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
    static struct arraycache_init initarray_generic =
        { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };

      이 함수 의 기타 보조 함 수 는 다음 과 같다. 1. 3 체인 초기 화 함수
    static void kmem_list3_init(struct kmem_list3 *parent)
    {
        INIT_LIST_HEAD(&parent->slabs_full);
        INIT_LIST_HEAD(&parent->slabs_partial);
        INIT_LIST_HEAD(&parent->slabs_free);
        parent->shared = NULL;
        parent->alien = NULL;
        parent->colour_next = 0;
        spin_lock_init(&parent->list_lock);
        parent->free_objects = 0;
        parent->free_touched = 0;
    }

    이것 은 별 쓸모 가 없다. 단지 초기 화 일 뿐이다.
    #define ALIGN(x,a)      __ALIGN_MASK(x,(typeof(x))(a)-1)
    #define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))

    이 매크로 는 메모리 가 a 의 크기 를 기본 단위 로 정렬 하 는 것 을 제어 하 는 데 사 용 됩 니 다. 0 ~ 7 을 한 그룹 으로 유추 합 니 다.
    이 매크로 에 대한 상세 한 설명 은 참조 할 수 있 습 니 다. 커 널 매크로 ALIGN 의 의 미 는 81943 입 니 다. cache estimate () 함수 라 는 함 수 는 모든 slab 의 대상 의 수량 과 공간 을 낭비 하 는 크기 를 계산 하 는 데 사 용 됩 니 다. 주석 중의 관리 대상 은 앞에서 말 한 관리자 입 니 다.
    /*
     * Calculate the number of objects and left-over bytes for a given buffer size.
     */
    static void cache_estimate(unsigned long gfporder, size_t buffer_size,
                   size_t align, int flags, size_t *left_over,
                   unsigned int *num)
    {
        int nr_objs;
        size_t mgmt_size;
    
        //slab     2^gfporder    
        size_t slab_size = PAGE_SIZE << gfporder;  //#define PAGE_SIZE 0x400 ( 1024),FIXME:         1K ,    ?
    
        /*
         * The slab management structure can be either off the slab or  // off-slab on-slab    
         * on it. For the latter case, the memory allocated for a
         * slab is used for:   //         :
         *
         * - The struct slab      //slab   
         * - One kmem_bufctl_t for each object    //     kmem_bufctl_t
         * - Padding to respect alignment of @align  //     
         * - @buffer_size bytes for each object   //       
         *
         * If the slab management structure is off the slab, then the
         * alignment will already be calculated into the size. Because   //   off-slab,align       
         * the slabs are all pages aligned, the objects will be at the   //           ,             
         * correct alignment when allocated.
         */
         //    slab,  slab      ,                   
        if (flags & CFLGS_OFF_SLAB) {
            //  slab       ,      slab  
            mgmt_size = 0;
            //       = slab   /     
            nr_objs = slab_size / buffer_size;    //  buffer_size   cache line    
    
            //        
            if (nr_objs > SLAB_LIMIT)
                nr_objs = SLAB_LIMIT;
        } else {
            /*
             * Ignore padding for the initial guess. The padding
             * is at most @align-1 bytes, and @buffer_size is at
             * least @align. In the worst case, this result will
             * be one greater than the number of objects that fit
             * into the memory allocation when taking the padding
             * into account.
             */
             //   slab,slab     slab         ,  slab    :
             //  struct slab   ,  kmem_bufctl_t     (kmem_bufctl_t       slab      )
            //slab            ,             / (       + sizeof(kmem_bufctl_t)),           
            nr_objs = (slab_size - sizeof(struct slab)) /
                  (buffer_size + sizeof(kmem_bufctl_t));
    
            /*
             * This calculated number will be either the right
             * amount, or one greater than what we want.
             */
             //       slab     ,        
            if (slab_mgmt_size(nr_objs, align) + nr_objs*buffer_size
                   > slab_size)
                nr_objs--;
    
            //        
            if (nr_objs > SLAB_LIMIT)
                nr_objs = SLAB_LIMIT;
    
            //                     
            mgmt_size = slab_mgmt_size(nr_objs, align);
        }
    
    
        //  slab      
        *num = nr_objs;
    
    
        //       slab      (   0,      ),         slab        
        *left_over = slab_size - nr_objs*buffer_size - mgmt_size;
    }

      5. malloc sizes [] 표 는 kmem cache create () 함 수 를 통 해 유 니 버 설 버퍼 를 만들어 야 합 니 다. 최종 적 으로 파트너 시스템 에 신청 합 니 다. 얼마나 만 들 까요? 재 미 있 는 곳 이 있 습 니 다. 먼저 INDEX AC 를 보 세 요.
    #define INDEX_AC index_of(sizeof(struct arraycache_init))

    index of 는 다음 과 같 습 니 다:
    /*
     * This function must be completely optimized away if a constant is passed to
     * it.  Mostly the same as what is in linux/slab.h except it returns an index.
     */
    static __always_inline int index_of(const size_t size) //           ,   mallloc_size     
    {
        extern void __bad_size(void);
    
        if (__builtin_constant_p(size)) {
            int i = 0;
    
    #define CACHE(x) \
        if (size <=x) \     //         size   
            return i; \
        else \
            i++;   //   ,      
    #include "linux/kmalloc_sizes.h"
    #undef CACHE
            __bad_size();
        } else
            __bad_size();
        return 0;
    }   

    왜 index of 가 크기 를 정할 수 있다 고 말 하 는 지, 이 건 정말 판 타지 입 니 다. 이 말 에 주의 하 세 요.
    #include "linux/kmalloc_sizes.h"

    linux / kmalloc sizes. h 의 내용 은 다음 과 같 습 니 다.
    #if (PAGE_SIZE == 4096)
        CACHE(32)
    #endif
        CACHE(64)
    #if L1_CACHE_BYTES < 64
        CACHE(96)
    #endif
        CACHE(128)
    #if L1_CACHE_BYTES < 128
        CACHE(192)
    #endif
        CACHE(256)
        CACHE(512)
        CACHE(1024)
        CACHE(2048)
        CACHE(4096)
        CACHE(8192)
        CACHE(16384)
        CACHE(32768)
        CACHE(65536)
        CACHE(131072)
    #if KMALLOC_MAX_SIZE >= 262144
        CACHE(262144)
    #endif
    #if KMALLOC_MAX_SIZE >= 524288
        CACHE(524288)
    #endif
    #if KMALLOC_MAX_SIZE >= 1048576
        CACHE(1048576)
    #endif
    #if KMALLOC_MAX_SIZE >= 2097152
        CACHE(2097152)
    #endif
    #if KMALLOC_MAX_SIZE >= 4194304
        CACHE(4194304)
    #endif
    #if KMALLOC_MAX_SIZE >= 8388608
        CACHE(8388608)
    #endif
    #if KMALLOC_MAX_SIZE >= 16777216
        CACHE(16777216)
    #endif
    #if KMALLOC_MAX_SIZE >= 33554432
        CACHE(33554432)
    #endif

    index of 함수 에서 CACHE (x) 매크로 를 부분 적 으로 정의 하고 이 헤더 파일 을 도입 합 니 다. 이 는 헤더 파일 의 모든 내용 을 index of 함수 의 그 문장 이 있 는 위치 에 추가 한 것 으로 이해 할 수 있 습 니 다. 그러면 프로그램 은 다음 에 끊임없이 실행 자 부분 매크로 CACHE (X) 를 실행 합 니 다.이 매크로 는 함수 적 의미 가 있 습 니 다. 정확 한 size 에 맞 으 면 i 값 을 직접 되 돌려 줍 니 다.
    그러면 아래 표 시 된 i 의 값 만 알 면 안 됩 니 다. malloc sizes [] 표 는 언제 초기 화 되 었 습 니까? 정 답 은 정적 으로 초기 화 되 었 습 니 다.
    /*
     * These are the default caches for kmalloc. Custom caches can have other sizes.
     */
    struct cache_sizes malloc_sizes[] = {  //         malloc_size   
    #define CACHE(x) { .cs_size = (x) },
    #include    //           
        CACHE(ULONG_MAX)
    #undef CACHE
    };

    위의 코드 에서 똑 같이 CACHE (X) 를 정 의 했 지만 이것 은 이전의 그 역할 과 다 릅 니 다. 그들 둘 은 모두 부분 매크로 이 고 사용 한 후에 undef 이 므 로 영향 을 주지 않 습 니 다.
    이 매크로 는 "{. cs size = (x)}" 로 정의 되 어 있 습 니 다. 이 쉼표 에 주의 하 시 겠 습 니까? 아래 는 kmalloc size 헤더 파일 에 있 는 많은 CACHE (x) 를 도입 합 니 다. 각각 이 형식 입 니 다. 이것 이 바로 배열 의 초기 화 방식 이 아 닙 니까? 모든 데이터 형식 이 cache size 형식 일 뿐 입 니 다. int array [] = {1}, {2},..} 에 해당 합 니 다., 대충 그렇습니다. cache names [] 표 는 같 습 니 다.
    cache sizes 형식 은 다음 과 같 습 니 다.
    /* Size description struct for general caches. */
    struct cache_sizes {
        size_t          cs_size;    //        
        struct kmem_cache   *cs_cachep;   //           
    #ifdef CONFIG_ZONE_DMA
        struct kmem_cache   *cs_dmacachep;
    #endif
    };

    따라서 위 와 같은 초기 화 방식 을 통 해 malloc sizes [] 표 에서 작은 것 부터 큰 순 으로 모든 cache sizes 의 cs size 구성원 을 초기 화 합 니 다. 따라서 malloc size [i] 는 크기 의 버퍼 를 설명 하 는 cache sizes 구조 에 대응 합 니 다. cs cachep 를 통 해 해당 하 는 크기 의 유 니 버 설 버퍼 를 얻 을 수 있 습 니 다!
    DMA 라면 두 가지 유 니 버 설 버퍼 를 설정 합 니 다.  8. init_list () 함수
    /*
     * swap the static kmem_list3 with kmalloced memory
     */
    static void init_list(struct kmem_cache *cachep, struct kmem_list3 *list,
                int nodeid)
    {
        struct kmem_list3 *ptr;
    
        ptr = kmalloc_node(sizeof(struct kmem_list3), GFP_KERNEL, nodeid);
        BUG_ON(!ptr);
    
        local_irq_disable();
        memcpy(ptr, list, sizeof(struct kmem_list3));
        /*
         * Do not assume that spinlocks can be initialized via memcpy:
         */
        spin_lock_init(&ptr->list_lock);
    
        MAKE_ALL_LISTS(cachep, ptr, nodeid);
        cachep->nodelists[nodeid] = ptr;
        local_irq_enable();
    }

    이것 은 kmalloc 를 이용 하여 3 체인 과 정적 3 체인 교환 을 신청 하 는 함수 입 니 다. 왜 kmalloc 를 이용 하 는 것 이 라 고 말 합 니까? 호출 된 kmalloc 를 보 세 요.node () 함수:
    static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
    {
        return kmalloc(size, flags);
    }   

    바로 이 렇 습 니 다. 우 리 는 '닭 과 알' 문 제 를 해결 하기 위해 먼저 몇 개의 정적 변 수 를 설정 합 니 다. 예 를 들 어 세 개의 체인 initkmemlist 3, 우선 그것 으로 우리 의 cache 를 합성 합 니 다.cache, 그리고 cachecache, 이것 은 버퍼 를 위 한 규칙 적 인 버퍼 입 니 다. 이 를 통 해 우 리 는 크기 의 다른 버퍼 를 마음대로 합성 할 수 있 습 니 다.kmemcache_init () 함수 후반 부 에 kmalloc 할당 대상 을 버퍼 로 사용 할 수 있 습 니 다. 교체 하기 전에 모든 보조 cachecache 의 정적 데이터 구조 (예 를 들 어 initarray cache, initkmem list 3) 는 이후 에 이러한 정적 데이터 구 조 는 더 이상 사용 하지 않 을 것 이다.
    cache_cache 는 버퍼 크기 를 위 한 규칙 을 만 들 었 습 니 다. 이 는 모든 버퍼 자체 의 크기 도 같 지만 buffer 에 불과 합 니 다.size 필드 에서 설명 하 는 분배 대상 의 크기 가 다 릅 니 다. 앞으로 서로 다른 크기 의 대상 은 이것 으로 서로 다른 버퍼 를 찾 아 분배 하면 됩 니 다.
    참고:
  • kmem_cache_init 텍스트 해석 초기 화
  • Linux Slab 분배 기 (一) – 개술
  •   PS: 요즘 왜 그래 요? 당 황 스 러 워 요. 며칠 배 워 서 이런 걸 배 웠 는데 성취 감 이 없 는 것 같 아 요.응, 당황 하지 않 았 어. 기술 을 하 는 사람 은 마음 을 가 라 앉 히 고.

    좋은 웹페이지 즐겨찾기