티스토리 뷰
4-114
create_kmalloc_caches
kmalloc 캐시를 CACHE_BYTES 부터 배수로 미리 생성
3 부터 2의 배수로 사용하고 0,1 은 96, 192 사이즈
KMALLOC_MIN_SIZE : 캐시 라인 크기
4-115
create_kmalloc_cache
kmem_cache_zalloc: zalloc 은 0으로 모두 set 한다는 의미 -> 452 페이지에서 다시 나옴
kmem_cache 구조체를 할당하기 위한 kmem_cache 객체를 사용. 이것 또한 keme_cache 를 받는 slab 에서 받아오는 것
4.7.4 kmem 캐시 생성 (p426)
4-116
kmem_cache_create
kmem 캐시를 생성
4-117
_kmem_cache_alias
이전에 만들어둔 kmem 캐시와 병합이 가능하다면 해당 kmem 캐시의 object size, inuse(워드 단위 정렬) 를 갱신하고 리턴한다.
#define for_each_memcg_cache(iter, root) \
list_for_each_entry(iter, &(root)->memcg_params.list, \
memcg_params.list)
-> memcg_cache 가 정확히 뭔지는 모르겠으나, kmem_cache 에 memcg_params 가 있음. 이것도 kmem_cache 이고 똑같이 정렬4-114
-> kmem_cache 는 글로벌 캐시이고, memcg_params 는 메모리 그룹별 캐시인건가?
4-118
find_mergeable
kmem cache 의 병합 조건
- slub_nomerge, SLAB_NEVER_MERGE 를 사용중이면 안됨
- 객체에 생성자를 붙여서 사용중이면 안됨
- 루트 캐시가 아니어야 함
- align size 가 동일해야함 등등
struct kmem_cache {
size: object_size 에 metadata 와 함께 align 맞춘 값 calculate_sizes 에서 지정됨
}
4-119
sysfs_slab_alias
같은 slab cache 를 사용할 수 있다면 링크로 연결, 아직 부팅 프로세스 중이라면 지연처리
struct kobject {
struct kernfs_node *sd; /* sysfs directory entry */
}
이후에 at dt 등 심볼릭 링크의 이름은 slub.c 의 create_unique_id 에서 정해지는 듯 하다
ls /sys/kernel/slab/ -l | grep 4096
lrwxrwxrwx 1 root root 0 11월 9 17:18 names_cache -> :t-0004096
lrwxrwxrwx 1 root root 0 11월 9 17:18 sgpool-128 -> :t-0004096
4-120
create_cache
다른 kmem_cache 를 사용할 수 없을때 생성
s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL); // kmem_cache 를 생성
err = __kmem_cache_create(s, flags);
4-121
__kmem_cache_create
생성된 cache 를 초기화 하고, kmem 캐시 디렉토리에 추가한다.
memcg_propagate_slab_attrs -> root kmem_cache 의 attribute 를 복사
static struct attribute *slab_attrs[] = {
&slab_size_attr.attr,
&object_size_attr.attr,
각 항목은 매크로로 정의되어 있음. 결국 slab_attribute 라는 구조체가 나옴
SLAB_ATTR_RO(object_size);
#define SLAB_ATTR_RO(_name) \
static struct slab_attribute _name##_attr = \
__ATTR(_name, 0400, _name##_show, NULL)
struct slab_attribute {
struct attribute attr;
ssize_t (*show)(struct kmem_cache *s, char *buf); // kmem_cache -> buf
ssize_t (*store)(struct kmem_cache *s, const char *x, size_t count); // x-> s
};
sysfs_slab_add: filesystem 에 slab cache 를 추가
kset -> filesystem 에서 사용하는 타입같은걸로 보임
static struct kset ext4_kset = {
.kobj = {.ktype = &ext4_ktype},
};
kobject_init_and_add - initialize a kobject structure and add it to the kobject hierarchy
커널 객체를 그룹화 하기 위한게 kset 이고 kobject 에 kset 을 설정 할 수 있음
__kmem_cache_release : cpu 와 node 의 캐시를 클리어해줌
4-122
kmem_cache_open
생성된 kmem cache 를 초기화
슬랩 페이지의 해제를 RCU 방식을 사용하는 경우, 해제가 더 빠르지만 구현이 복잡하다. RCU 를 사용하는 경우 reserve 에 rcu head 크기를 설정한다.
if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU))
s->reserved = sizeof(struct rcu_head);
kmem_cache->min_partial 은 뭘까? 객체의 size 를 표현하는데 필요한 비트수의 절반을 저장함
- min_partial: 미리 생성해둘 객체수 정도 인 것 같다. (페이지 수인지 객체수인지는 좀더 봐야겠지만 일단은 객체수로)
kmem_cache->cpu_partial 은 뭘까? 이것도 size 에 따라 결정됨
- 각 CPU는 자신만의 cpu_partial 리스트를 유지하여, 다른 CPU들과의 경쟁을 최소화하고 메모리 할당을 최적화
calculate_sizes
kmem_cache 의 size 를 계산한다.
SLAB_RED_ZONE: object 뒤에 무조건 padding 비슷한 redzone 을 둠. 따라서 size = object_size 라면 word 하나만큼 추가
그 외에도 옵션에 따라 size 에 metadata 를 추가
static inline struct kmem_cache_order_objects oo_make(int order, unsigned long size, int reserved)
oo = order_objects
calculat_order(int size, int reserved)
calculate_sizes 에서 order 를 계산중
object 를 최소 몇개정도 넣을 수 있는 페이지 order 를 구한다
몇개나 object 가 들어갈 수 있는지 표현하는 것 같다.
static inline int order_objects(int order, unsigned long size, int reserved)
{
return ((PAGE_SIZE << order) - reserved) / size;
}
max_objects = order_objects(slub_max_order, size, reserved); // 들어갈 수 있는 최대
min_objects = min(min_objects, max_objects); // 최소 개수 정해두기
slab_order(size, min_objects, slub_max_order, fraction, reserved)
fraction: 허용할 수 있는 "낭비"의 비율
4-123
init_kmem_cache_nodes
노드를 돌면서 kmem cache 를 설정한다. 아직 부팅중이라면 버디를 사용, 그렇지 않다면 슬랩을 사용한다.
4-124
slub.c early_kmem_cache_node_alloc
slab 할당자가 활성화 되기 전, 캐시 노드를 초기화 하기 위해 버디 시스템을 사용한다.
page = new_slab(kmem_cache_node, GFP_NOWAIT, node); // 버디에서 슬랩용 페이지를 가져온다.
이때 page 의 설정을 바꿔줌
page->freelist = fixup_red_left(s, start);
page->inuse = page->objects;
page->frozen = 1; // freelist 를 직접 관리하겠다는 의미
static inline void *get_freepointer(struct kmem_cache *s, void *object)
{
return *(void **)(object + s->offset);
} // -> 448페이지의 그림 참고. offset 을 더하면 FP(Free Pointer)
n = page->freelist; 이 freelist 는 이미 버디용이 아니라 slap 용임.
BUG_ON(!n);
page->freelist = get_freepointer(kmem_cache_node, n); 처음 비어있는 객체의 주소를 설정
page->inuse = 1;
page->frozen = 0; // 다시 unfrozen 하는 이유?
kmem_cache_node->node[node] = n;
'개발 > 코드로 알아보는 ARM 리눅스 커널 TIL' 카테고리의 다른 글
20241123 4.7.6 슬랩 객체 할당 (p449) & 4.7.7 슬랩 객체 해제 (0) | 2024.11.30 |
---|---|
20241116 4.7.5슬랩 페이지와 슬랩 객체 할당 (p442) (1) | 2024.11.21 |
241102 메모리 관리 (p394) & 4.7 슬랩 할당자 (p410) (2) | 2024.11.21 |
20241026 4.6.9 slowpath 페이지 할당 (p388) (0) | 2024.11.20 |
20241019 4.6 페이지 할당자 (p356) (0) | 2024.11.20 |
- Total
- Today
- Yesterday
- vr핏
- print shared_ptr class member variable
- hole-punching
- mysql
- 에러 위치 찾기
- Golang
- 면접
- set value
- Visual Studio
- cockroach db
- it's called a vrpit
- SuffixArray
- 봄날에 스케치
- C++
- 우리는 vr핏이라고 부릅니다
- RVO
- 잘못된 빨간줄
- vrpit
- Obstacle Avoidance
- red underline
- shared_from_this
- boost
- 코어 남기기
- 영상 픽셀화 하기
- 클래스 맴버 변수 출력하기
- 카카오
- chrome-extension
- Reciprocal n-body Collision Avoidance
- ad skip
- Quest2
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |