글 수 117
1. 시작
> 위치: linux/init/main.c
2. 전체 구성도
asmlinkage void __init start_kernel(void)
{
time_init();
profile_init(); // 2008-03-14 profile 초기화 , prof_buffer 메모리 할당
if (!irqs_disabled())
printk("start_kernel(): bug: interrupts were enabled earlyn");
early_boot_irqs_on();
local_irq_enable(); //
console_init(); // 시리얼 콘솔을 초기화한다.
if (panic_later)
panic(panic_later, panic_param);
lockdep_info(); // do nothing
locking_selftest();
#ifdef CONFIG_BLK_DEV_INITRD // blcok device
if (initrd_start && !initrd_below_start_ok && // ramdisk 주소사 첫번째 프래임(2^12) 크기 보다 작으면 에러
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
vfs_caches_init_early();
cpuset_init_early();
mem_init();
kmem_cache_init();
}
2.1. profile_init();
> 역할 :
- prof_buffer 메모리 할당을 한다.
> 상세 :
할당되는 메모리 크기는 다음과 같다.
prof_len = (_etext - _stext) >> prof_shift;
2.2 irqs_disabled()
> 역할 :
- 현재의 인터럽트 가능 상태를 저장한 후
- 인터럽트를 disable 하게 한다.
> 상세 :
start_kernel()이 수행 되는 동안 irq를 disable 한다.
2.3 early_boot_irqs_on()
> 역할 :
- invalid irq가 on
- flag (early_boot_irqs_enabled)를 통해, early bootup code 안에 있는지 혹인 할 수 있다.
2.4 local_irq_enable()
> 역할 :
- 현재 부팅 중인 cpu 의 interrupt를 활성화 한다.
(현재 mpcore 를 분석한다점에 주목하지 cpu 가 2개)
-
2.5 console_init()
> 역할 :
- tty_ldisc 의 정의 중에서 comment 중에서
The following routines are called from above.
The following routines are called from below.
를 볼 수 있다.
즉, tty_ldisc 구조체가 어떤 시스템의 구성 요소 들간의 연결하는 역할을 한다는 것을 알 수 있다.
이것은 실제로 리눅스에서 터미널 구현하는 곡에서 사용되며,
하위 드라이버를 연결하거나,
상위에 가상터미널과 같은 것을 둘 경우에 사용 될 수 있을 것이다.
> 참조 : kelp.or.kr/korweblog/upload/12/20020316003912/Embedded_Linux_17_start_kernel_fun_7.pdf
> 함수 원형
void __init console_init(void)
{
initcall_t *call; // 함수 포인터
/* Setup the default TTY line discipline.
* 새로운 ldisc 의 하나의 포인터를 넘겨 받아 , 전역의로 선언된 tty_ldiscs 의 entry로 저장한다.
*/
(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
/* 함수 포인터를 이용해서 함수를 실행하는 건데 __con_initcall_start 는 어디서 등록하지 ???
* 2.4.2 를 참고해요...^^
* __con_initcall_start 위치 : linux/arch/arm/kernel/vmlinux.lds.S 에 있다.
*/
call = __con_initcall_start; // 컴파일시 섹션에 함수 포인터 설정
while (call < __con_initcall_end) {
(*call)(); // 섹셤?
call++;
}
}
2.5.1 __con_initcall_start
> 위치 :
- linux/arch/arm/kernel/vmlinux.lds.S 에 있다.
> 내용 :
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
> 상세
console_init() 을 보면 __con_initcall_start 의 pointer를 call(함수포인터) 넘기고
__con_initcall_end까지 while을 도는 것을 확인 할 수 있다.
즉 start ~end 까지 지덩한 함수를 실행하는 것이다.
여기서 발생하는 의문은 다음과 같다.
1) when 언제 함수가 등록되는가.
2) where 어디서 __con_initcall_start 부터 __con_initcall_end까지 까지 함수를 등록하는가?
1)when ? 대한 의문을 풀어 보자.
커널이 컴파일 되면서 등록함수가 _con_initcall_start 부터 __con_initcall_end 의 section에 등록된다.
2) where ? 에 대한 의문을 풀어 보자.
등록시키는 함수는 console_initcall() 이고 함수의 원형은, 아래와 같다.
#define console_initcall(fn)
static initcall_t __initcall_##fn
__attribute_used__ __attribute__((__section__(".con_initcall.init")))=fn
console_initcall()를 호출하는 곳은 대부분 /drivers 의 시리얼과 관련된 곳에서 찾을 수 있다.
<검색 결과>
---- console_initcall Matches (46 in 45 files) ----
21285.c (driversserial):console_initcall(rs285_console_init);
68328serial.c (driversserial):console_initcall(m68328_console_init);
8250.c (driversserial):console_initcall(serial8250_console_init);
8250_early.c (driversserial):console_initcall(early_uart_console_init);
Amiserial.c (driverschar):console_initcall(amiserial_console_init);
Atmel_serial.c (driversserial):console_initcall(atmel_console_init);
Clps711x.c (driversserial):console_initcall(clps711xuart_console_init);
Common.c (archarmplat-omap):console_initcall(omap_add_serial_console);
Con3215.c (driverss390char):console_initcall(con3215_init);
.
.
Vme_scc.c (driverschar):console_initcall(vme_scc_console_init);
Vr41xx_siu.c (driversserial):console_initcall(siu_console_init);
Vt.c (driverschar):console_initcall(con_init);
2.6 lockdep_info()
> 역할 :
- 아무것도 안한다.
2.7 CONFIG_BLK_DEV_INITRD
> 역할 :
- ramdisk 주소가 첫번째 프래임(2^12) 크기 보다 작으면 에러
> 참고 :
http://lxr.linux.no/linux/Documentation/initrd.txt
initial RAM filesystem 은 부트로더에 의해 로딩된는 ramfs이다.
이것은. 일반적 boot 과정 전에 root처럼 mount 된다.
"real" root file system를 mount 하는데 필요한 모듈을 loading 하는데 사용된다.
CONFIG_BLK_DEV_INITRD (RAM disk support) 를 포함 시키면, initail RAM disk 지원 및
커널 사이즈 15K(arch에 따라 다름)를 추가한다.
2.8 vfs_caches_init_early()
> 역할 :
> 함수 원형
void __init vfs_caches_init_early(void)
{
dcache_init_early();
inode_init_early();
}
나머지는 친구랑 막걸리 한사발 먹고 와서 정리하지요.^^;
스프링 노트는 사용번 익히면 옮겨 놀께요.
틀린 부분 지적해 주세요.
왠지 껍데기만 쓴 느낌..대략 난감 하군요.