장소 : 영통 모이자 (3PM ~ 11PM)
인원 : 목태양 외 12명
진도 : 리눅스 커널 내부구조 (~P111 Buddy와 Slab까지)
스터디 중 얘기한 내용
- [전원] 수원 인근 스터디 장소 찾아보고 댓글로 공유하기
- [전원] arch 결정 필요. 각자 생각해서 다음주에 다수결로 arch 정하기 (x86, arm 또는 arm64)
- 스터디는 커널 교재 -> 아키텍쳐 교재 -> 커널 코드 분석 순으로 진행 예정
- 필요한 사람은 리눅스 커널 코드 분석 및 테스트 앱 실행 가능한 개발 환경 구축하기 (효율적으로 공부하는데 도움됨)
- 스터디 시간 중 충분히 토론하여 완결성 있게 공부하되, 개인별로 필요한 만큼 예복습 등 추가 공부
- 참고자료 1 : ARM 리눅스 커널 코드로 알아보는 http://book.naver.com/bookdb/book_detail.nhn?bid=6980387
- 참고자료 2 : 문C블로그 http://jake.dothome.co.kr/
추가 내용
- [전원] 5/20(토) 스터디 참석 인원은 5/16(화)까지 확정하고, 화요일까지 취합한 인원 기준으로 5/17(수)에 스터디룸 대여합니다. 현금으로 스터디룸 대여료 걷는 것이 번거로우니 스터디룸 N빵도 스터디 전날(5/19)까지 계좌이체로 처리합니다. 5/16(화) 이후 참석 의사를 밝히실 경우 스터디룸 정원 문제로 어려움이 있을 수 있으니 미리 참석 의사 밝혀주세요.
댓글 3
-
감데공
2017.05.14 20:27
-
목태양
2017.05.15 10:52
스터디 시간 중에 얘기했던 것 중 커널 스레드에 관해서, 리눅스 커널 심층분석 책에 있는 내용 공유합니다.
커널 스레드가 커널 동작의 일부를 백그라운드에서 수행하며, 일반 태스크와의 주요한 차이점은 커널 스레드에는 주소 공간이 없다는 것입니다.
(task struct의 struct mm_struct *mm, *active_mm; 필드가 NULL인 것 같네요.)
커널 스레드는 커널 공간에서만 동작하며 사용자 공간으로 컨텍스트 전환이 일어나지 않고, 정상 프로세스와 마찬가지로 커널 스레드도 스케줄링/선점 가능하다고 합니다.
스터디 시간에 추론한 것과 일치하는 거 같네요..
Kernel Threads
It is often useful for the kernel to perform some operations in the background.The kernel
accomplishes this via kernel threads—standard processes that exist solely in kernelspace.
The significant difference between kernel threads and normal processes is that
kernel threads do not have an address space. (Their mm pointer, which points at their
address space, is NULL.) They operate only in kernel-space and do not context switch into
user-space. Kernel threads, however, are schedulable and preemptable, the same as normal
processes.
Linux delegates several tasks to kernel threads, most notably the flush tasks and the
ksoftirqd task.You can see the kernel threads on your Linux system by running the command
ps -ef.There are a lot of them! Kernel threads are created on system boot by
other kernel threads. Indeed, a kernel thread can be created only by another kernel
thread.The kernel handles this automatically by forking all new kernel threads off of thekthreadd kernel process.The interface, declared in <linux/kthread.h>, for spawning a
new kernel thread from an existing one is
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data,
const char namefmt[],
...)
The new task is created via the clone() system call by the kthread kernel process.The
new process will run the threadfn function, which is passed the data argument.The
process will be named namefmt, which takes printf-style formatting arguments in the variable
argument list.The process is created in an unrunnable state; it will not start running
until explicitly woken up via wake_up_process().A process can be created and made
runnable with a single function, kthread_run():
struct task_struct *kthread_run(int (*threadfn)(void *data),
void *data,
const char namefmt[],
...)
This routine, implemented as a macro, simply calls both kthread_create() and
wake_up_process():
#define kthread_run(threadfn, data, namefmt, ...) \
({ \
struct task_struct *k; \
\
k = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
if (!IS_ERR(k)) \
wake_up_process(k); \
k; \
})
When started, a kernel thread continues to exist until it calls do_exit() or another
part of the kernel calls kthread_stop(), passing in the address of the task_struct structure
returned by kthread_create():
int kthread_stop(struct task_struct *k)
We discuss specific kernel threads in more detail in later chapters. -
목태양
2017.05.15 12:36
스터디 중 얘기했던 내용 중 "각 태스크별 페이지 테이블은 어디에 저장되는가" 하는 의문점에 대해서 좀더 확인해봤습니다. (커널 버전 4.1.X, arch/arm 기준)
제가 보기에 각 태스크별 페이지 테이블은 ZONE NORMAL에 저장되는 것 같은데, 밑에 내용 한 번 읽어보시고 의견 있으시면 공유 부탁드립니다.스터디 시간에 잠시 봤던 task_struct 구조체에는 struct mm_struct *mm 멤버가 있습니다.
그리고 mm_struct 구조체에는 pgd_t * pgd; 멤버가 있습니다.
(task A의 task_struct) -> mm ->pgd가 task A의 1단계 페이지 테이블을 가리키는 것으로 보입니다.
cf 1) 문 C 블로그 페이지 테이블 관련 내용 : http://jake.dothome.co.kr/pt/그런데 역시 스터디 시간에 잠시 봤던 do_fork 함수(사용자가 fork systemcall 호출시 수행되는 main fork-routine)를 좀 살펴보면
do_fork->copy_mm->dup_mm->mm_init->mm_alloc_pgd->pgd_alloc 경로로, 프로세스 생성시 pgd 테이블을 위한 페이지가 할당되는 것 같습니다.
pgd_alloc 함수의 내용은 아래와 같습니다.pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *new_pgd, *init_pgd;
pud_t *new_pud, *init_pud;
pmd_t *new_pmd, *init_pmd;
pte_t *new_pte, *init_pte;new_pgd = __pgd_alloc();
if (!new_pgd)
goto no_pgd;
memset(new_pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
...#ifdef CONFIG_ARM_LPAE
#define __pgd_alloc() kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL)
#define __pgd_free(pgd) kfree(pgd)
#else
#define __pgd_alloc() (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, 2)
#define __pgd_free(pgd) free_pages((unsigned long)pgd, 2)
#endifCONFIG_ARM_LPAE config가 false인 경우에 한해 __get_free_pages 함수를 호출하여 page를 할당합니다.
그리고 __get_free_pages 함수는 내부적으로 alloc_pages를 호출합니다.
리눅스 커널 심층분석 책에 보면, alloc_pages 함수는 2order(1<<N === 2^N) 만큼 연속된 물리적 페이지를 할당하고 첫번째 페이지의 page 구조체 포인터를 반환한다. 고 되어 있습니다.
따라서 4개 page(16KB)를 pgd를 위해 할당하는 것으로 보입니다.
한편 alloc_pages 함수의 인자로 GFP_KERNEL 플래그를 사용하므로, 할당되는 페이지의 위치는 NORMAL ZONE일 것으로 생각됩니다. GFP_KERNEL매크로의 정의는 아래와 같습니다.
#define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS)DMA ZONE이나 HIGHMEM ZONE에 할당 요청하려면 ___GFP_DMA나 ___GFP_HIGHMEM FLAG를 포함하는 매크로를 인자로 줘야 할 것 같습니다.
cf 2) 문 C 블로그 GFP flag 관련 내용 : http://jake.dothome.co.kr/gfp-flag/
.
https://docs.google.com/spreadsheets/d/1QteLbtnsuW9J-SkTv0BqNKOnWtq1n3FR9R0fc42sHoc/edit?usp=sharing
참여여부 작성 구글 스프레드 시트입니다.
참여가능하신분은 자신의 이름의 참여라고 적어주세요.