Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>
커널 시작

5.1. 커널 시작

4.4.2절(5)에서 start_kernel이 불리는데 여기 부터가 일반 적인 커널의 시작이라고 생각하면 된다.

start_kernel 전 까지는 리눅스 커널이 실행되기 위한 기본 적인 초기화 등을 해놓은 상태라고 생각하면 된다. 아래에 start_kernel()만을 발췌해 놨다. 또 커널 부팅 중 남은 기록은 5.8절를 참조 바란다.

/*
 *	Activate the first processor.
 */

asmlinkage void __init start_kernel(void)
{
	char * command_line;
	unsigned long mempages;
	extern char saved_command_line[];
/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
(1)
	lock_kernel();
(2)
	printk(linux_banner);
(3)
	setup_arch(&command_line);
(4)
	printk("Kernel command line: %s\n", saved_command_line);
(5)
	parse_options(command_line);
(6)
	trap_init();
(7)
	init_IRQ();
(8)
	sched_init();
(9)
	softirq_init();
(10)
	time_init();

	/*
	 * HACK ALERT! This is early. We're enabling the console before
	 * we've done PCI setups etc, and console_init() must be aware of
	 * this. But we do want output early, in case something goes wrong.
	 */
(11)
	console_init();
#ifdef CONFIG_MODULES
(12)
	init_modules();
#endif
	if (prof_shift) {
		unsigned int size;
		/* only text is profiled */
		prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
		prof_len >>= prof_shift;
		
		size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;
		prof_buffer = (unsigned int *) alloc_bootmem(size);
	}

(13)
	kmem_cache_init();
(14)
	sti();
(15)
	calibrate_delay();
#ifdef CONFIG_BLK_DEV_INITRD
	if (initrd_start && !initrd_below_start_ok && 
			initrd_start < min_low_pfn << PAGE_SHIFT) {
		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
		    "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
		initrd_start = 0;
	}
#endif
(16)
	mem_init();
(17)
	kmem_cache_sizes_init();
	pgtable_cache_init();

	mempages = num_physpages;

(18)
	fork_init(mempages);
(19)
	proc_caches_init();
(20)
	vfs_caches_init(mempages);
	buffer_init(mempages);
	page_cache_init(mempages);
#if defined(CONFIG_ARCH_S390)
	ccwcache_init();
#endif
	signals_init();
#ifdef CONFIG_PROC_FS
	proc_root_init();
#endif
#if defined(CONFIG_SYSVIPC)
(21)
	ipc_init();
#endif
(22)
	check_bugs();
	printk("POSIX conformance testing by UNIFIX\n");

	/* 
	 *	We count on the initial thread going ok 
	 *	Like idlers init is an unlocked kernel thread, which will
	 *	make syscalls (and thus be locked).
	 */
(23)
	smp_init();
(24)
	rest_init();
}

(1)
5.2절 참조
(2)
linux_banner는 init/version.c에 다음과 같이 정의되어 있다.

const char *linux_banner = 
	"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
	LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";

이 내용은 부팅할 때 아래와 같이 출력되고 /var/log/dmesg의 첫 줄에 기록된다.

Linux version 2.4.16 (root@localhost) (gcc version 2.95.3 20010315 (release)) #22 2002. 02. 27. (수) 13:30:14 KST

(3)
5.3절 참조
(4)
화면에 command line option을 출력한다.
(5)
command line option을 해석한다. 여기에서 해석되는 것은 모두 커널 내부적으로 사용되는 것이고 init로 보내지진 않는다.

해석된 옵션은 '='가 있으면 환경 변수로 취급되고 없으면 옵션을 처리되 환경 변수는 envp_init[]에 담기고 옵션은 argv_init[]에 담긴다.

(6)
5.4절 참조
(7)
5.5절 참조
(8)
5.6절 참조
(9)
소프트웨어 인터럽트를 기본 시스템을 초기화 한다. bh에 대한 초기화가 이뤄지기도 한다.
(10)
CMOS에서 시간을 읽고 CPU의 속도를 얻어낸다. /var/log/dmesg에 "Detected 1009.016 MHz processor."라고 출력되는 부분이기도 하다.
(11)
콘솔 디바이스를 초기화 한다. 모든 초기화를 수행하는 것은 아니고 초기에 필요한 정도만 하고 나머지는 나중에 한다. dmesg에 'Console: colour VGA+ 132x43'를 출력한다.
(12)
모듈의 초기화를 하지만 i386, ARM에선 아무 것도 하지 않는다. ia64만 뭔가를 한다.
(13)
대부분의 슬랩 배정자(slab allocator)를 초기화 한다.
(14)
인터럽트를 가능하게 한다.
(15)
BogoMIPS를 계산한다. dmesg에 'Calibrating delay loop... 2011.95 BogoMIPS'라고 출력된다.
(16)
max_mapnr, totalram_pages, high_memory를 계산하고 dmesg에 'Memory: 512920k/524208k available (1213k kernel code, 10900k reserved, 482k data, 228k init, 0k highmem)'라고 출력한다.
(17)
슬랩 초기화를 마친다.
(18)
uid_cache를 만들고 사용 가능한 메모리의 양에 따라 max_threads를 초기화하고 RLIMIT_NPROC을 max_threads/2로 정한다.
(19)
procfs가 사용하는 데이터 스트럭쳐를 초기화 한다.
(20)
VFS, VM, buffer cache 등에 대한 슬램 캐시를 만든다.
(21)
System V IPC가 지원되는 커널이라면 IPC 하부 시스템을 초기화 한다. 세마포어, 메시지큐, 공유메모리를 초기화 한다.
(22)
아키텍쳐에 따른 버그를 검사한다. 예를 들어 ia32의 "f00f 버그"다.
(23)
멀티 프로세서 시스템이 가능한 아키텍쳐의 경우에만 해당하는 내용으로 SMP를 초기화 한다.
(24)
rest_init() 자체는 무척 간단하다. 우선 init 프로세스를 실행해 준다. 그리고 start_kernel()의 첫 부분에서 lock 했던 커널을 unlock 해주고 idle 상태로 들어간다. idle 상태로 들어가도 이미 init 프로세스가 생성된 후기 때문에 상관 없이 커널의 부팅은 진행된다. idle 프로세스는 0번의 프로세스 번호를 갖는다.

나머지에 대해선 5.7절 참조