[Research] Linux Kernel Basic - (3) 커널에서의 메모리 할당 1편

[Research] Linux Kernel Basic - (3) 커널에서의 메모리 할당 1편

서론

해당 포스트에서는 리눅스 커널(Linux Kernel)에서도 연산을 수행하기 위해서 데이터가 저장되어야만 하는 공간이 있어야 한다. 이러한 공간의 주체는 메모리(memory)이며 리눅스 커널(Linux Kernel)에서의 메모리의 할당 방식을 알아본다.

정적 메모리

커널에서의 정적 메모리 할당에 대하여 구체적으로 알아보려고 한다. 유저 공간의 할당과 마찬가지로 정적 메모리 할당은 특징을 지닌다.


1. 함수 호출 시 함수 프롤로그의 절차를 통해 스택에 공간을 할당한다.
2. 유저 공간과는 별개의 커널의 스택 공간이 할당된다.
3. 컴파일 시 스택 공간에 얼마만큼의 데이터를 활용할 것인지에 관해 결정된다.
4. 함수 호출 시 함수 에필로그의 절차를 통해 정적 메모리는 자동으로 해제된다.

위의 기재된 내용은 일반적인 유저공간의 스택공간의 할당과 동일해보인다. 부가적인 내용을 붙히자면 컴파일을 통해 스택 프레임의 최상위에서 sub연산을 통해 공간을 확보하고 함수 호출이 종료되는 시점에서 스택 프레임의 최상위에서 add연산을 통해 프레임을 해제한다. 이 후 함수가 호출되어도 스택 포인터(frame pointer)와 베이스 포인터(base pointer)를 기준으로 접근하기에 일반적인 경우라면 문제 발생의 소지가 없다.


1
2
3
4
5
6
7
8
9
void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) {
int prio, oldprio, queued, running, queue_flag =
DEQUEUE_SAVE | DEQUEUE_MOVE | DEQUEUE_NOCLOCK;
const struct sched_class *prev_class;
struct rq_flags rf;
struct rq *rq;

prio = __rt_effective_prio(pi_task, p->normal_prio);
...

다음의 코드를 확인하면 8개의 변수를 활용하는 것을 알 수 있다.


1
2
3
4
5
6
7
8
<rt_mutex_setprio>:
e1a0c00d mov ip, sp
e92ddff0 push {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
e24cb004 sub fp, ip, #4
e24dd014 sub sp, sp, #20
.
.
.

해당 함수의 어셈블리 코드를 확인하면 레지스터 {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}를 스택 공간에 push하며 sub sp, sp, #20을 통해 스택의 20바이트의 공간 만큼을 확보한다. 이 때 사용되는 지역변수의 개수는 8개이며 32바이트 만큼의 공간을 확보해야 한다고 의문이 드나 이는 내부적으로 레지스터를 활용하는 방안으로 진행되지 않았을까라고 조심스럽게 판단한다. 자세한 부분은 b30w0lf님께 여쭤봐야 할 것으로 보인다.

동적 메모리

커널에서의 동적 메모리 할당에 대하여 구체적으로 알아보려고 한다. 커널에서의 메모리 할당은 kmalloc() 함수를 이용하여 동적 메모리를 할당한다.

1
2
3
4
5
6
7
8
9
10
static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from,
unsigned int to, char __user *user_buf, size_t count, loff_t *ppos)
{
...
if (*ppos < 0 || !count)
return -EINVAL;

buf = kmalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;

상단의 코드를 확인하면 kmalloc() 함수를 볼 수 있으며 해당 함수는 두 개의 인자 count와 GFP_KERNEL이 전달되는 것을 확인할 수 있다. 종합해 코드를 해석하면 GFP_KERNEL 옵션을 통해 count 바이트 만큼 동적 메모리를 할당한다라는 의미이다. kmalloc을 이용하면 커널 내부 메모리 시스템의 경우 커널 내부에 할당할 동적 메모리가 있으면 최대한 할당해준다고 한다.

결론

정적 메모리의 할당은 유저 공간(user space)에서의 스택 공간할당은 커널 메모리 공간에 할당된다. 이외에는 크게 다른 점이 없어보이며 동적 메모리 할당은 kmalloc() 함수를 사용한다이다. 단 의아한 부분이 커널 내부에 할당할 동적 메모리가 있으면 최대한 할당해준다고 하는 의미인다. 이는 슬랩(slab)에 대한 개념을 익혀야 더욱 깊게 이해가 가능할 것으로 보인다.

참고자료

http://rousalome.egloos.com/10002615