440 likes | 522 Views
Gerenciamento de Memória. Leandro Marzulo. Roteiro. Páginas Zonas Operações com Páginas kmalloc() vmalloc() Slab Layer Alocação estática na Pilha High Memory Mappings Alocação “Per-CPU” Qual método de alocação usar?. Roteiro. Páginas Zonas Operações com Páginas kmalloc()
E N D
Gerenciamento de Memória Leandro Marzulo
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Páginas • Unidade básica de Gerenciamento de memória • Tamanho relacionado com a arquitetura (4KB ou 8 KB) • Struct page <linux/mm.h> struct page { page_flags_t flags; //Status da página //<linux/page-flags.h> atomic_t _count; //Contador de referências //page_count() atomic_t _mapcount; unsigned long private; struct address_space *mapping; //cache pgoff_t index; struct list_head lru; void *virtual; //endereço virtual //NULL para HIGH MEM };
Páginas • Struct page - páginas físicas • Estrutura descreve algo transiente • Descrição da memória física • Saber quais são as páginas livres • Saber quem é o dono de cada página ocupada • TAMANHO OCUPADO PELAS STRUCTS 1GB = 262144 páginas (de 4KB) Struct page = 40 bytes 40 * 262144 = 10485760 bytes = 10MB Menos de 1% da memória total
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Zonas • Arquiteturas que fazem DMA apenas em alguns endereços • Arquiteturas que podem endereçar fisicamente mais memória do que podem endereçar virtualmente • Zonas <linux/mmzone.h>
Zonas • Pooling independente • Alocação para DMA só pode vir da ZONE_DMA • Alocação normal vem, preferencialmente de ZONE_NORMAL, mas pode vir de ZONE_DMA
ZONAS • Struct zone <linux/mmzone.h> struct zone { spinlock_t lock; //Proteção contra //acessos concorrentes unsigned long free_pages; //num de pgs. livres unsigned long pages_min; //kernel tenta manter //o mín livre (swap) unsigned long pages_low; unsigned long pages_high; . . . unsigned long zone_start_pfn; char *name; //nome da zona – “DMA” //”Normal” e “HighMem” //(inicializado no boot) // <mm/page_aloc.c> unsigned long spanned_pages; unsigned long present_pages; };
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Operações com Páginas • Pegando páginas <linux/gfp.h> struct page * alloc_pages(unsigned int gfp_mask, unsigned int order) //Aloca 2order páginas contíguas void * page_address(struct page *page) //retorna ponteiro para o endereço lógico unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order) //retorna o endereço lógico /* PARA ALOCAR UMA PÁGINA */ struct page * alloc_page(unsigned int gfp_mask) unsigned long __get_free_page(unsigned int gfp_mask)
Operações com Páginas • Pegando uma página Zerada • Liberando páginas unsigned long get_zeroed_page(unsigned int gfp_mask) void __free_pages(struct page *page, unsigned int order) void free_pages(unsigned long addr, unsigned int order) void free_page(unsigned long addr)
Operações com Páginas • Exemplo unsigned long page; page = __get_free_pages(GFP_KERNEL, 3); if (!page) { // TRATAR ERRO – MEMÓRIA INSUFICIENTE return ENOMEM; } . . . free_pages(page, 3);
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Kmalloc() • Interface para obter memória em bytes ao invés de páginas • = malloc + flags • Declaração <linux/slab.h> • Exemplo void * kmalloc(size_t size, int flags) /* retorna um ponteiro para região fisicamente contínua de no mínimo “size” bytes (alocação é feita em páginas na realidade)*/ struct dog *ptr; ptr = kmalloc(sizeof(struct dog), GFP_KERNEL); if (!ptr) /* Erro ... */
Kmalloc() • Flags <linux/gfp.h> • Action Modifiers – como o kernel deve alocar a memória requisitada (Manipuladores de interrupção kernel não pode “dormir”) • Zone Modifiers – de onde o kernel deve alocar a memória requisitada • Type flags – combinação de “Action Modifiers” e “Zone Modifiers” necessários para um determinado tipo de alocação • Exemplo ptr = kmalloc(size, __GFP_WAIT | __GFP_IO | __GFP_FS);
Kmalloc() • Action Modifiers
Kmalloc() • Zone Modifiers • Default – ZONE_NORMAL • __GFP_HIGHMEM não pode ser usado em __get_free_pages() ou kmalloc(). É usado com alloc_pages()
Kmalloc() • Type Flags
Kmalloc() • Type Flags – Composição
Kmalloc() • Flags – Uso
Kmalloc() • E para liberar a memória? • Kfree() <linuxslab.h> • Exemplo void kfree(const void *ptr) char *buf; buf = kmalloc(BUF_SIZE, GFP_ATOMIC); if (!buf) /* error allocting memory ! */ . . . kfree(buf);
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Vmalloc() • Semelhante ao kmalloc(), porém aloca memória virtualmente contígua e não necessariamente fisicamente contígua • A maior parte do kernel usa kmalloc() • Performance do kmalloc é melhor (TLB) • Declaração <linux/vmalloc.h> <mm/vmalloc.c> • Para liberar a memória void * vmalloc(unsigned long size) void vfree(void *addr)
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Slab Layer • Free Lists • Problema: Controle Global – Liberar memória • Conceito de Slab Alocator • Estruturas de dados frequentemente usadas tendem a ser alocadas e liberadas constantemente – CACHE • Fragmentação de memória – as free lists na CACHE são arrumadas continuamentea • Melhoria de performance • O alocador conhece o tamanho do objeto, página e da cache – melhores decisões • Parte da cache é implementada por processador (SMP lock desnecessário) • Se o alocador é NUMA-aware, ele pode procurar alocar memória do nó que requisitou • Os objetos armazenados podem ser marcados para prevenir que múltiplos objetos sejam mapeados na mesma linha de cache
Slab Layer • Design
Slab Layer • Uma cache por tipo de objeto • Kmalloc() usa uma família de caches de propósito geral • Slabs compostas de uma ou mais paginas fisicamente contíguas • Cada Slab contem um número de objetos • Slab possui 3 estados: full, partial ou empty
Slab Layer • Struct slab • Criação de slabs feita em struct slab { struct list_head list; /* full, partial, or empty list */ unsigned long colouroff; /* offset for the slab coloring */ void *s_mem; /* first object in the slab */ unsigned int inuse; /* allocated objects in the slab */ kmem_bufctl_t free; /* first free object, if any */ }; __get_free_pages()
Slab Layer • Exemplo • Liberando memória (low mem ou cache destruida) static inline void * kmem_getpages(kmem_cache_t *cachep, unsigned long flags) { void *addr; flags |= cachep->gfpflags; addr = (void*) __get_free_pages(flags, cachep->gfporder); return addr; } kmem_freepages() free_pages()
Slab Layer • Criação de cache kmem_cache_t * kmem_cache_create( const char *name, //nome da cache size_t size, //tamanho de cada elemento size_t align, //offset unsigned long flags, //comportamento da cache void (*ctor)(void*, kmem_cache_t *, unsigned long), //construtor void (*dtor)(void*, kmem_cache_t *, unsigned long)) //destrutor
Slab Layer • Destruindo a cache • Invocada pelo shutdown de modulos que criam suas próprias caches • Não pode ser chamada no contexto de interrupção (pode dormir) • Todas as slabs devem estar vazias • Ninguém pode acessar a cache durante ou depois (sincronização) int kmem_cache_destroy(kmem_cache_t *cachep)
Slab Layer • Alocando um objeto da cache • Liberando um objeto void * kmem_cache_alloc(kmem_cache_t *cachep, int flags) void kmem_cache_free(kmem_cache_t *cachep, void *objp)
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Alocação Estática na Pilha • Pilha pequena e estática • Duas formas • 2 páginas por processo • 1 página por processo + 1 para manipuladores de interrupção
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
High Memory Mappings • Mapeamento permanente (pode dormir) • Mapeamento temporário void *kmap(struct page *page) void kunmap(struct page *page) void *kmap_atomic(struct page *page, enum km_type type) void kunmap_atomic(void *kvaddr, enum km_type type)
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?
Alocação “Per-CPU” • Razões para usar • Evitar Locks • Reduzir Invalidação de cache
Alocação “Per-CPU” Problemas com preempção do kernel • Código pode ser reescalonado em outro processador (variável CPU não é mais válida • Se outra task faz preempção pode acessar o my_percpu concorrentemente • Interface Antiga unsigned long my_percpu[NR_CPUS]; int cpu; cpu = get_cpu(); //pega o proc e desablita preemp my_percpu[cpu]++; smp_processor_id(); //não desabilita preemp printk("my_percpu on cpu=%d is %lu\n", cpu, my_percpu[cpu]); put_cpu(); //habilita preemp
Alocação “Per-CPU” • Nova Interface DEFINE_PER_CPU(type, name); DECLARE_PER_CPU(type, name); get_cpu_var(name)++; put_cpu_var(name); /* preemption */ per_cpu(name, cpu)++; void *alloc_percpu(type); /* a macro */ void *__alloc_percpu(size_t size, size_t align); void free_percpu(const void *); get_cpu_ptr(ptr); /* return a void pointer to this processor's copy of ptr */ put_cpu_ptr(ptr); /* done; enable kernel preemption */ per_cpu_ptr(ptr, cpu);
Roteiro • Páginas • Zonas • Operações com Páginas • kmalloc() • vmalloc() • Slab Layer • Alocação estática na Pilha • High Memory Mappings • Alocação “Per-CPU” • Qual método de alocação usar?