Start_Kernel (Week 2)
Start_Kernel (Week 2)

Start_Kernel (Week 2)

카테고리
⚙️ Start Kernel
작성자
박용성박용성
작성일
2024년 06월 02일
태그
C
Linux
 

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)
  1. CONFIG_STACK_GROWSUP 매크로가 정의되어 있는 경우
      • 스택이 위에서 아래로 자라는 Architecture인 경우 해당함
      • return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1; 가 컴파일됨
      • task_thread_info 함수를 활용해 task_struct 에서 해당 task의 스레드 정보를 가져옴
        • → 스택의 끝을 계산함
  1. 매크로가 정의되어 있지 않은 경우
      • 스택이 아래에서 위로 자라는 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
notion image
/** * 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); }
 
매크로의 역할?
 
 
 

댓글

guest