void start_kernel(void)set_task_stack_end_magic(&init_task);smp_setup_processor_id()debug_objects_early_init();
void start_kernel(void)
- 위치 :
init/main.c Line:874
void start_kernel(void) { char *command_line; char *after_dashes; set_task_stack_end_magic(&init_task); smp_setup_processor_id(); debug_objects_early_init(); init_vmlinux_build_id(); cgroup_init_early(); ...
command_line
커널 명령 행에 대한 포인터를 가리킴 (시스템 부팅 시 커널에 전달되는 매개 변수 문자열)
root=/dev/sda1 rw init=/sbin/init
after_dashes
parse_args
함수의 결과를 포함하며 입력 문자열을 'name = value'형식의 매개 변수로 구문 분석하여 특정 키워드를 찾고 매칭되는 핸들러를 호출set_task_stack_end_magic(&init_task);
init_task
의 주소를 불러와 STACK_END_MAGIC
을 카나리아로 설정함- 카나리아 : 스택 오버플로우와 같은 메모리 오염 공격을 방지하기 위한 기법
// 정의로 이동, kernel/fork.c void set_task_stack_end_magic(struct task_struct *tsk) { unsigned long *stackend; stackend = end_of_stack(tsk); *stackend = STACK_END_MAGIC; /* for overflow detection */ }
// 정의로 이동, include/linux/sched/task_stack.h static inline unsigned long *end_of_stack(struct task_struct *p) { #ifdef CONFIG_STACK_GROWSUP return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1; #else return (unsigned long *)(task_thread_info(p) + 1); #endif }
// 정의로 이동, include/linux/sched.h # define task_thread_info(task) ((struct thread_info *)(task)->stack)
CONFIG_STACK_GROWSUP
매크로가 정의되어 있는 경우- 스택이 위에서 아래로 자라는 Architecture인 경우 해당함
return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1;
가 컴파일됨task_thread_info
함수를 활용해task_struct
에서 해당 task의 스레드 정보를 가져옴
→ 스택의 끝을 계산함
- 매크로가 정의되어 있지 않은 경우
- 스택이 아래에서 위로 자라는 Architecture인 경우 해당함
- +1을 하는 이유는 스택의 시작이 스레드 정보 바로 다음 위치에 있기 때문 (?)
→ 따라서
end_of_stack
함수는 스택의 끝을 계산하기 위해 사용됨smp_setup_processor_id()
weak
속성으로 선언되는 빈 함수. x86에는 해당 기능이 존재하지 않음- SMP
사용중인 상태면 접근 X
사용중이 아니라면 접근하고 LOCK 해두기
debug_objects_early_init();
CONFIG_DEBUG_OBJECTS
옵션이 켜져 있으면 해당 함수를 호출해 관련 자료구조를 초기화// 정의로 이동, lib/debugobjects.c void __init debug_objects_early_init(void) { int i; for (i = 0; i < ODEBUG_HASH_SIZE; i++) raw_spin_lock_init(&obj_hash[i].lock); for (i = 0; i < ODEBUG_POOL_SIZE; i++) hlist_add_head(&obj_static_pool[i].node, &obj_pool); }
// raw_spin_lock_init 정의로 이동, include/linux/spinlock.h #ifdef CONFIG_DEBUG_SPINLOCK extern void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name, struct lock_class_key *key, short inner); # define raw_spin_lock_init(lock) \ do { \ static struct lock_class_key __key; \ \ __raw_spin_lock_init((lock), #lock, &__key, LD_WAIT_SPIN); \ } while (0) // 왜 While문을 사용했지? #else # define raw_spin_lock_init(lock) \ do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); } while (0) #endif
/** * hlist_add_head - add a new entry at the beginning of the hlist * @n: new entry to be added * @h: hlist head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. */ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; WRITE_ONCE(n->next, first); if (first) WRITE_ONCE(first->pprev, &n->next); WRITE_ONCE(h->first, n); WRITE_ONCE(n->pprev, &h->first); }
매크로의 역할?
댓글