Princípio do mecanismo de laje

Aquisição de laje - o método de aquisição mais eficiente

Alocar e liberar estruturas de dados é uma das operações mais comuns em todos os kernels. Para facilitar a alocação e recuperação freqüentes de dados, uma lista vinculada a espaço é freqüentemente usada. É equivalente a um cache de objeto para armazenar rapidamente tipos de objetos usados ​​com frequência. No kernel, um dos principais problemas da lista gratuita é que ela não pode ser controlada globalmente. Quando a memória disponível fica apertada, o kernel não pode notificar cada lista vinculada livre para diminuir o tamanho do cache a fim de liberar alguma memória. Na verdade, o kernel não tem ideia de que existe um offshore gratuito. Para compensar esse defeito e tornar o código mais estável, o kernel do Linux fornece uma camada slab (o chamado classificador slab), e o classificador slab desempenha o papel de uma camada de cache de estrutura de dados geral. O distribuidor de placas tenta encontrar um equilíbrio entre os seguintes princípios:

1. Estruturas de dados usadas com freqüência também são alocadas e liberadas com freqüência, portanto, devem ser armazenadas em cache.

2. A alocação e recuperação frequentes levarão inevitavelmente à fragmentação da memória. Para evitar essa situação, o cache da lista vinculada livre será armazenado continuamente. Como a estrutura de dados liberada será colocada de volta na lista livre, não causará fragmentação. 3. O objeto recuperado pode ser colocado na próxima alocação imediatamente, portanto, para alocação e liberação frequentes, a lista livre pode melhorar seu desempenho. 4. Se parte do cache for dedicada a um único processador, então a alocação e a liberação podem ser realizadas sem bloqueios SMP. 5. Pinte os objetos armazenados para evitar que vários objetos sejam mapeados para a mesma linha de cache.

A camada slab divide objetos diferentes nos chamados grupos de cache, onde cada cache armazena diferentes tipos de objetos, e cada tipo de objeto corresponde a um cache. A interface kmalloc () é construída na camada slab e usa um conjunto de caches de uso geral. Esses caches são divididos em placas, sendo a placa composta por uma ou mais páginas fisicamente contínuas, em geral a placa é composta por apenas uma página Cada cache pode ser composto de várias placas. Cada placa contém alguns membros do objeto. O objeto aqui se refere à estrutura de dados a ser armazenada em cache. Cada placa está em um dos três estados: cheia, parcialmente cheia e vazia. Quando uma certa parte do kernel precisa de um novo objeto, primeiro aloque-o da placa parcialmente cheia. Se não houver laje parcialmente cheia, ela será alocada a partir da laje vazia. Se não houver nenhuma laje vazia, uma laje deve ser criada.

mecanismo de alocação de placas

O alocador de blocos é gerenciado com base em objetos.Os chamados objetos são estruturas de dados no kernel (por exemplo: task_struct, file_struct, etc.). Objetos do mesmo tipo são classificados em uma categoria, sempre que se candidatar a tal objeto, o alocador de lajes aloca uma unidade desse tamanho de uma lista de lajes, e quando for liberada, será salva na lista novamente. Em vez de retornar diretamente ao sistema parceiro, evitando assim a fragmentação interna. O alocador de blocos não descarta os objetos alocados, mas os libera e os salva na memória. Quando o slab aloca um objeto, ele usa o bloco de memória do objeto lançado mais recentemente, portanto, a probabilidade de ele permanecer no cache da cpu será muito melhorada.

A principal estrutura de dados da placa no kernel

Insira a descrição da imagem aqui

Analise resumidamente a seguinte figura: kmem_cache é uma lista vinculada de cache_chain, descrevendo um cache, cada cache contém uma lista de blocos, que normalmente é um bloco de memória contínuo. Existem três tipos de lajes: slabs_full (laje totalmente alocada), slabs_partial (laje parcialmente alocada), slabs_empty (laje vazia ou nenhum objeto está alocado). A placa é a menor unidade do distribuidor de placas.Na implementação, uma placa consiste em uma ou mais páginas físicas consecutivas (geralmente apenas uma página). Uma única laje pode ser movida entre as listas encadeadas de lajes. Por exemplo, se uma laje meio cheia ficar cheia depois de ser alocada um objeto, ela será excluída de slabs_partial e inserida em slabs_full ao mesmo tempo.

Princípio de realização da camada de laje

O cache no Linux é implementado pela chamada camada slab, que é o mecanismo de gerenciamento do cache no kernel.

O princípio de toda a camada de laje é o seguinte:

O cache de vários objetos pode ser estabelecido na memória (como o cache de task_struct relacionado à descrição do processo).
Além do cache para objetos específicos, também existem caches para objetos gerais.
Cada cache contém vários blocos, que são usados ​​por blocos. O
bloco de objetos usado para gerenciar o cache contém vários objetos em cache, que são fisicamente compostos por uma ou mais páginas consecutivas
. A relação entre cache-> bloco-> objetos de cache é a seguinte:

Insira a descrição da imagem aqui

Aplicação de camada de laje

Para a definição da estrutura da laje, consulte:

struct slab {
    
    
    struct list_head list;   /* 存放缓存对象,这个链表有 满,部分满,空 3种状态  */
    unsigned long colouroff; /* slab 着色的偏移量 */
    void *s_mem;             /* 在 slab 中的第一个对象 */
    unsigned int inuse;         /* slab 中已分配的对象数 */
    kmem_bufctl_t free;      /* 第一个空闲对象(如果有的话) */
    unsigned short nodeid;   /* 应该是在 NUMA 环境下使用 */
};

Existem quatro métodos principais para a aplicação da camada de laje:

Criação de cache
Alocar objetos
do cache Liberar objetos para o
cache Destruir o cache

/**
 * 创建高速缓存
 */
struct kmem_cache *
kmem_cache_create (const char *name, size_t size, size_t align,
    unsigned long flags, void (*ctor)(void *))

/**
 * 从高速缓存中分配对象
 * @cachep - 指向高速缓存指针
 * @flags  - 之前讨论的 gfp_mask 标志,只有在高速缓存中所有slab都没有空闲对象时,
 *           需要申请新的空间时,这个标志才会起作用。
 *
 * 分配成功时,返回指向对象的指针
 */
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)

/**
 * 向高速缓存释放对象
 * @cachep - 指向高速缓存指针
 * @objp   - 要释放的对象的指针
 */
void kmem_cache_free(struct kmem_cache *cachep, void *objp)

/**
 * 销毁高速缓存
 * @cachep - 指向高速缓存指针 
 */
void kmem_cache_destroy(struct kmem_cache *cachep)

Insira a descrição da imagem aqui

[Benefícios do artigo] O editor recomenda meu próprio grupo de intercâmbio técnico Linux e C / C ++: [960994558] Compilei alguns livros de aprendizagem e materiais de vídeo que acho que são melhores para compartilhar (incluindo C / C ++, Linux, Nginx, ZeroMQ, MySQL) , Redis, fastdfs, MongoDB, ZK, streaming media, CDN, P2P, K8S, Docker, TCP / IP, corrotina, DPDK, etc.), você mesmo pode adicioná-lo se precisar! ~

Acho que você gosta

Origin blog.csdn.net/weixin_52622200/article/details/110875673
Recomendado
Clasificación