리눅스 커널 코드를 분석하다보면 분명 작성된 언어는 C언어인데 처음보는 낯선 키워드등 분석이 잘 안되는 경우가 있습니다.
이는 메크로함수나 함수 포인터 등 #define으로 새로 정의되어 사용되는 키워드들 때문에 가독성이 떨어지기 때문입니다.
그 중 한 예로 리눅스의 스케줄링을 담당하는 schedule() 함수를 보면,
이렇게 함수가 구성되어 있습니다.
이를 하나씩 살펴 보겠습니다.
asmlinkage는 어셈블리와 링크가 가능하다는 뜻 즉, 어셈블리어로 짜여진 코드에서 이 함수를 호출 할 수 있다는 뜻입니다.
__sched 이 키워드는 linux/include/linux/sched.h에 정의 되어 있습니다.
다음과 같은 형태로 정의되어 있는데 ( 점점 더 복잡하게 되는 것 같습니다. )
__attribute__ 는 윈도우의 #pragma 와 비슷한 것으로 c의 표준은 아닙니다.
#pragma는 cl컴파일러에서 작동하며, __attribute__는 gcc컴파일러에서 작동하며 사용되는 용도는 비슷합니다.
__attribute__ 키워드의 대표적인 예로는
이런 구조체가 있을때 sizeof(asdf) 라고 하면 결과는 8이 나옵니다.
라고 했을 때 결과는 5가 나옵니다.
이는 packing(natural boundary)때문에 일어나는 현상입니다.
이를 정확한 값을 얻고 싶다면
이렇게 하면 정확한 값이 나옵니다. (윈도우에서는 #pragma pack(1) 라고 하면 됩니다.)
이 외에 __attribute__(x) 안에 들어갈 수 있는 것은 여러가지가 있습니다.
그럼 다시 돌아와서 살펴 보도록 하겠습니다.
이 키워드는 ".sched.text라는 섹션을 만들어서 그 섹션안에 schedule()함수의 내용을 넣어라" 라는 뜻이 됩니다.
이렇게 함으로써 얻을 수 있는 이점으로 섹션은 build 타임에 relocation이 가능하게 되는데,
초기화 역할을하는 특정 섹션을 만들어 그 안에 넣은 후 사용하다가 더이상 필요 없을 시 이 섹션을 날려 버립니다.
이런 방식으로 메모리 공간을 아낄 수 있습니다.
리눅스에서는 보통 커널공간이 1GB이고, 유저공간이 3GB입니다.(설정에 따라 달라질 수는 있습니다.)
만약 task_struct등 커널 오브젝트의 증가나 컨택스트 스위칭 등 커널 자원을 소비하는 작업을 할 때 커널 공간이 부족하다면 시스템 운영상 곤란 할 것입니다.
실제로 start_kernel() 함수도
asmlinkage void __init start_kernel(void)
이렇게 정의되어 있습니다.
즉 .text.init섹션에 start_kernel함수의 내용을 넣었다가 초가화가 끝나고 나면 이 섹션을 날리면서 메모리 공간을 절약합니다.
이렇게 리눅스에서는 커널공간을 효율적으로 관리하고 있습니다.
관련된 pdf파일을 첨부합니다. 관련된 내용은 아주 조금 있지만 전반적으로 읽어두면 커널을 이해하는데 조금 도움이 될듯합니다.
출처 : http://teamcrak.tistory.com/130
이는 메크로함수나 함수 포인터 등 #define으로 새로 정의되어 사용되는 키워드들 때문에 가독성이 떨어지기 때문입니다.
그 중 한 예로 리눅스의 스케줄링을 담당하는 schedule() 함수를 보면,
asmlinkage void __sched schedule(void)
이렇게 함수가 구성되어 있습니다.
이를 하나씩 살펴 보겠습니다.
asmlinkage는 어셈블리와 링크가 가능하다는 뜻 즉, 어셈블리어로 짜여진 코드에서 이 함수를 호출 할 수 있다는 뜻입니다.
__sched 이 키워드는 linux/include/linux/sched.h에 정의 되어 있습니다.
#define __sched __attribute__((__section__(".sched.text")))
다음과 같은 형태로 정의되어 있는데 ( 점점 더 복잡하게 되는 것 같습니다. )
__attribute__ 는 윈도우의 #pragma 와 비슷한 것으로 c의 표준은 아닙니다.
#pragma는 cl컴파일러에서 작동하며, __attribute__는 gcc컴파일러에서 작동하며 사용되는 용도는 비슷합니다.
__attribute__ 키워드의 대표적인 예로는
typedef struct
{
{
char a;
int b;
int b;
}asdf;
이런 구조체가 있을때 sizeof(asdf) 라고 하면 결과는 8이 나옵니다.
int a = sizeof(char)+sizeof(int);
printf("%d\n", a);
printf("%d\n", a);
라고 했을 때 결과는 5가 나옵니다.
이는 packing(natural boundary)때문에 일어나는 현상입니다.
이를 정확한 값을 얻고 싶다면
typedef struct
{
{
char a;
int b;
int b;
}__attribute__(packed) asdf;
이렇게 하면 정확한 값이 나옵니다. (윈도우에서는 #pragma pack(1) 라고 하면 됩니다.)
이 외에 __attribute__(x) 안에 들어갈 수 있는 것은 여러가지가 있습니다.
그럼 다시 돌아와서 살펴 보도록 하겠습니다.
__attribute__((__section__(".sched.text")))
이 키워드는 ".sched.text라는 섹션을 만들어서 그 섹션안에 schedule()함수의 내용을 넣어라" 라는 뜻이 됩니다.
이렇게 함으로써 얻을 수 있는 이점으로 섹션은 build 타임에 relocation이 가능하게 되는데,
초기화 역할을하는 특정 섹션을 만들어 그 안에 넣은 후 사용하다가 더이상 필요 없을 시 이 섹션을 날려 버립니다.
이런 방식으로 메모리 공간을 아낄 수 있습니다.
리눅스에서는 보통 커널공간이 1GB이고, 유저공간이 3GB입니다.(설정에 따라 달라질 수는 있습니다.)
만약 task_struct등 커널 오브젝트의 증가나 컨택스트 스위칭 등 커널 자원을 소비하는 작업을 할 때 커널 공간이 부족하다면 시스템 운영상 곤란 할 것입니다.
실제로 start_kernel() 함수도
asmlinkage void __init start_kernel(void)
#define __init __attribute__ ((__section__ (".text.init")))
이렇게 정의되어 있습니다.
즉 .text.init섹션에 start_kernel함수의 내용을 넣었다가 초가화가 끝나고 나면 이 섹션을 날리면서 메모리 공간을 절약합니다.
이렇게 리눅스에서는 커널공간을 효율적으로 관리하고 있습니다.
관련된 pdf파일을 첨부합니다. 관련된 내용은 아주 조금 있지만 전반적으로 읽어두면 커널을 이해하는데 조금 도움이 될듯합니다.
출처 : http://teamcrak.tistory.com/130
'Linux > Kernel Programming' 카테고리의 다른 글
__builtin_constant_p (0) | 2010.08.31 |
---|---|
atomic_t in Linux Kernel (0) | 2010.03.06 |
WRITTEN BY
- RootFriend
개인적으로... 나쁜 기억력에 도움되라고 만들게되었습니다.
,