http://homep04.com/rtrb.php/pds
이 글은 사이트 kelp.or.kr 과 남상규씨 홈페이지(http://61.96.198.114)에서 발췌한
것입니다.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Linux kernel이 무엇을 수행하는 녀석인지는 설명 드리지 않겠습니다. OS kernel의 수
행이 무엇을 의미하는지를 다루는 것은 너무나도 방대하기 때문에 여기서 말씀드릴 내
용이 아니라고 생각됩니다. Linux kernel이 어디서부터 수행되고 결국에는 어떻게 끝
나는지(실제로는 시스템의 작동이 멈출 때까지는 끝나지는 않죠)만 간략히 말씀 드립
니다. (소스 코드에 대한 자세한 분석은 다른 자료들이 있을 겁니다.) 압축되지 않은
Linux kernel의 경우 보통 arch/*/kernel/head.S에 entry point가 있습니다.(압축되어
있는 linux kernel의 경우 보통 arch/*/boot/../head.S에 entry point가 있습니다. 그
entry point부터 수행되는 코드는 압축된 image를 메모리에 풀고 다시 압축되지 않는
kernel의 entry point로 jump하는 작업을 수행하게 됩니다.) 그 곳부터 수행이 시작되
어 architecture와 관련 있는 hardware를 초기화하고 C 코드가 수행될 수 있도록 하는
작업을 합니다.(보통은 Stack영역을 확보하고 BSS 섹션을 0로 초기화합니다.) 그 다음
은 init/main.c에 있는 start_kernel() 함수를 호출합니다.
start_kernel() 함수는 다시 arch_init, trap_init 등의 architecture dependent한 초
기화 함수를 부르고 linux kernel의 각 구성부분에 대한 초기화 함수를 호출합니다.
start_kernel() 함수의 맨 마지막 부분에서 드디어 kernel_thread(init, …)함수로
PID가 1인 kernel thread 를 하나 만들고 start_kernel() 함수 자체는 idle task가 됩
니다. init kernel thread는 root를 mount하고 다음과 같은 코드로 끝이 납니다.
(다른 kernel thread를 만들고 initrd와 관련된 재미있는 부분이 있습니다만…)
if (open("/dev/console", O_RDWR, 0) < 0)
printk("Warning: unable to open an initial console.\n");
(void) dup(0);
(void) dup(0);
if (execute_command)
execve(execute_command, argv_init, envp_init);
execve("/sbin/init", argv_init, envp_init);
execve("/etc/init", argv_init, envp_init);
execve("/bin/init", argv_init, envp_init);
execve("/bin/sh", argv_init, envp_init);
panic("No init found. Try passing init= option to kernel.");
코드 설명을 간단하게 해드리면 우선 /dev/console을 open 합니다.(file descriptor 0
에 열렸을 겁니다.) 그다음 dup system call을 이용하여 file descriptor 1번과 file
descriptor 2번을 똑 같은 device(/dev/console)로 만들어 줍니다. 당연히 file descr
iptor 0,1,2는 각각 standard input, output, error을 위해 사용되게 됩니다. 그 다음
execute_command라고 하는 kernel argument(init=…로 주는 argument입니다.)가 있으
면 그것을 exec하고 없으면 /sbin/init, /etc/init, /bin/init, /bin/sh 순으로
exec을 시도합니다. 하나라도 성공하면 PID 1번으로 그 프로세스가 동작하겠죠. 모두
실패하면 kernel panic이 납니다. (open, dup, exec등의 system call을 kernel 레벨에
서 사용한다니 재미있습니다. kernel 레벨에서 사용 가능한 system call은
include/asm/unistd.h에서 살펴보실 수 있습니다.) 보통의 PC기반 linux 시스템의
경우 /sbin/init이 exec될 겁니다. 그 프로그램이 바로 system V init 라는 프로그램
인데 user 레벨 초기화(IP address setting등)를 수행하고 데몬들을 부르는 여러 가지
shell script를 fork하고 getty를 fork하여 login메시지를 뿌리도록 하는 녀석입니다.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- start_kernel() 함수 : $Linux_src/init/main.c 에 정의
start_kernel 함수의 개략적인 동작 순서
1. Architecture에 특수한(혹은 의존적인) 설정
2. Paging 시스템에 대한 초기화
3. Exception(혹은 trap)에 대한 초기화
4. Interrupt에 대한 초기화
5. Scheduler의 초기화
6. Timer의 초기화
7. Console의 초기화
8. Module들의 초기화
9. Cache와 buffer의 초기화
10. 메모리 시스템의 초기화
11. 파일 시스템의 초기화
12. init 시스템 프로세스의 생성
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5장. 리눅스 커널 부팅
5.1절. 커널 시작
5.2절. lock_kernel()
5.2.1절. Lock이 왜 필요하지?
5.2.2절. Lock - 기초적 설명
5.2.3절. i386, ARM의 스핀락
5.3절. setup_arch()
5.4절. trap_init()
5.5절. init_IRQ()
5.6절. sched_init()
5.7절. init()
5.8절. dmesg 정리
5장. 리눅스 커널 부팅
start_kernel()함수의 시작과 함께 커널이 시작한다.
5.1절. 커널 시작
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();
:lock_kernel은 아키텍쳐마다 하나씩 따로 정의 된다. 시스템을 초기화하는 동안 락을
걸어둔다. 두개이상의 CPU가 있는경우 동시에 초기화작업을 하는것을 막기위해
(2)
printk(linux_banner);
: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)
setup_arch(&command_line);
:setup_arch()는 arch/*/kernel/setup.c에 각 아키텍쳐에 따른 정의가 되어 있다.
여기서는 아키텍쳐에 따른 설정을 한다. i386에서는 아래와 같은 정보를 수집하 거나
초기화 해 놓는다. CPU가 초기화 되면서 /var/log/dmesg에 "Initializing CPU#0"를 출
력한다.
- 기본 루트 디바이스 선택
- 시스템에 연결되어 있는 드라이브 정보 수집
- 화면 정보 수집
- APM 정보 수집
- 시스템 정보 수집
- 램디스크 플래그 설정
- 메모리 영역 설정
- 메모리 매니져 변수 초기화
- 커맨드 라인 명령 해석
- 부팅할 때 사용하는 메모리 초기화
- 페이징 시스템 초기화
- 전원 관리 초기화
- 표준 롬 초기화
ARM 의 경우 i386과는 달리 프로세서 종류가 몇 가지 되므로 프로세서와 아키텍쳐 타
입에 따른 설정을 마친 후 커맨드 라인 명령을 해석한다. 이어 메모리 설정을 초기화
하고 페이지 설정도 한다.
(4)
printk("Kernel command line: %s\n", saved_command_line);
:화면에 command line option을 출력한다.
(5)
parse_options(command_line);
:command line option을 해석한다. 여기에서 해석되는 것은 모두 커널 내부적으로
사용되는 것이고 init로 보내지진 않는다.
해석된 옵션은 '='가 있으면 환경 변수로 취급되고 없으면 옵션을 처리되 환경 변수는
envp_init[]에 담기고 옵션은 argv_init[]에 담긴다.
(6)
trap_init();
:트랩은 인터럽트와는 달리 정해진 곳으로 분기하도록 되어 있고 번호로 정해져 있다.
아래는 i386에서 정해져 있는 트랩의 일부를 열거한 것이다.
0 - divide_error
1 - debug
2 - nmi
3 - int3
4 - overflow
5 - bounds
6 - invalid_op
7 - device_not_available
8 - double_fault
9 - coprocessor_segment_overrun
10 - invalid_TSS
11 - segment_not_present
12 - stack_segment
13 - general_protection
14 - page_fault
15 - spurious_interrupt_bug
16 - coprocessor_error
17 - alignment_check
18 - machine_check
19 - simd_coprocessor_error
trap_init()에선 시스템 콜을 위한 초기화도 실행해 0x80을 시스템 콜에 사용하도록
해놓는다. 그리고 CPU를 초기화 한다. CPU 초기화에선 페이지, gdt, ldt, idt, tss 등
이 설정되고 이를 사용할 수 있는 상태로 만들어 본격적인 커널 실행에 들어간다.
/var/log/dmesg의 (6)에 출력된 한 줄이 CPU의 초기화를 의미한다.
i386에서 trap을 초기화하는 함수인 _set_gate()는 C.2.2절를 참조 하기 바란다.
ARM 프로세서의 trap은 arch/arm/kernel/entry-armv.S나 arch/arm/kernel/entry-armo.S
에 정의되어 있고 내용은 다음과 같다. 앞의 값은 vector의 offset을 말한다.
0x00000000 - reset
0x00000004 - Undefined instruction
0x00000008 - Software Interrupt(SWI)
0x0000000C - Prefetch Abort(Instruction fetch memory abort)
0x00000010 - Data Abort(Data Access memory abort)
0x00000018 - IRQ(Interrupt)
0x0000001C - FIQ(Fast Interrupt)
(7)
init_IRQ();
:i386의 PC 계열에선 ISA 혹은 APIC를 지원하는 시스템인 경우에 따라 인터럽트 설정을
하고 타이머 인터럽트를 동작시킨다. 아직은 인터럽트가 사용가능하지 않으므로 인터럽
트가 동작하진 않는다. 0x20 ~ 0x2f 까지의 벡터는 ISA 인터럽트용 벡터이고
0xf0 ~ 0xff는 SMP 시스템용 인터럽트 벡터로 사용된다. 나머지 0x30 ~ 0xee는 APIC가
사용한다. 단 0x80은 시스템 콜이 사용하므로 제외한다.
ARM Assabet 보드에 사용된 SA-1100 CPU의 경우 arch/arm/mach-sa1100/assabet.c에 정
의된 것에 따라 sa1100_init_irq가 불리게 된다. 다음과 같다. ARM의 경우 cpu가 같아
도 플랫폼이 다르거나 CPU의 종류도 많으므로 각 CPU나 시스템의 타입에 따라 다른 함
수를 사용할 수 있도록 만들어져 있다.
MACHINE_START(ASSABET, "Intel-Assabet")
BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
BOOT_PARAMS(0xc0000100)
FIXUP(fixup_assabet)
MAPIO(assabet_map_io)
INITIRQ(sa1100_init_irq)
MACHINE_END
(8)
sched_init();
:init 태스크가 사용하는 CPU 번로를 할당해 주고 pid hash table을 초기화 한다. 이어
타이머 인터럽트 벡터를 초기화 한다. 인터럽트 처리 루틴은 되도록이면 간결하고 빨라
야할 필요가 있다. 프로그램이 실행 중에 인터럽트가 걸리면 프로그램의 실행을 멈추고
인터럽트를 처리하므로 인터럽트 처리 시간이 많이 걸린다면 다른 프로그램의 실행에
영향을 미치게된다. 리눅스에선 긴 처리 시간을 필요로 하는 인터럽트 루틴 의 문제를
해결하기 위해 인터럽트 루틴을 둘로 나눠 이 문제를 해결한다.
이 둘을 top-half, bottom-half라고 부른다. top-half는 request_irq로 등록되는 부분
이고 bottom-half(줄여서 bh)는 나중에 시간이 충분할 때 실행되도록 top-half에 의해
스케쥴 된다.
top-half와 bh의 차이라면 bh가 실행되는 동안엔 다른 모든 인터럽트가 가능 상태인 것
이다. 즉 top-half는 인터럽트가 걸리면 처음 실행되고 디바이스의 데이터를 특정 버퍼
에 저장해 놓고 자신의 bh에 표시를 한다음 빠져나간다. 이렇게 하면 top-half는 매우
빠르게 실행되기 때문에 다른 것에 영향을 주지 않게 된다.
그러나 만약 top-half가 동작하는 중에 다른 인터럽트가 걸리면 이 것은 무시된다. 왜
냐면 top-half가 실행되는 동안엔 인터럽트 컨트롤러의 IRQ 라인이 불가능 상태이기
때문이다.
가장 대표적인 인터럽트 루틴인 네트워크 인터럽트 루틴은 새로운 패킷이 도착하면 핸
들러가 도착한 데이터만을 읽어 프로토콜 레이어에 전달하고 실제의 처리는 나중에
bh에 의해 나중에 실행된다.
스케쥴러의 초기화에선 가장 근본적인 3개의 bh를 초기화한다.
TIMER_BH, TQUEUE_BH, IMMEDIATE_BH의 3개이다.
(9)
softirq_init();
:소프트웨어 인터럽트를 기본 시스템을 초기화 한다. bh에 대한 초기화가 이뤄지기도 한다.
(10)
time_init();
:CMOS에서 시간을 읽고 CPU의 속도를 얻어낸다. /var/log/dmesg에
"Detected 1009.016 MHz processor."라고 출력되는 부분이기도 하다.
/*
* 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();
:콘솔 디바이스를 초기화 한다. 모든 초기화를 수행하는 것은 아니고 초기에 필요한
정도만 하고 나머지는 나중에 한다. dmesg에 'Console: colour VGA+ 132x43'를 출력한다.
#ifdef CONFIG_MODULES
(12)
init_modules();
:모듈의 초기화를 하지만 i386, ARM에선 아무 것도 하지 않는다. ia64만 뭔가를 한다.
#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();
:대부분의 슬랩 배정자(slab allocator)를 초기화 한다.
(14)
sti();
:인터럽트를 가능하게 한다.
(15)
calibrate_delay();
:BogoMIPS를 계산. dmesg에 'Calibrating delay loop... 2011.95 BogoMIPS'라고 출력.
#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();
:max_mapnr, totalram_pages, high_memory를 계산하고 dmesg에
'Memory: 512920k/524208k available (1213k kernel code, 10900k reserved, 482k data,
228k init, 0k highmem)'라고 출력한다.
(17)
kmem_cache_sizes_init();
pgtable_cache_init();
mempages = num_physpages;
:슬랩 초기화를 마친다.
(18)
fork_init(mempages);
:uid_cache를 만들고 사용 가능한 메모리의 양에 따라 max_threads를 초기화하고
RLIMIT_NPROC을 max_threads/2로 정한다.
(19)
proc_caches_init();
:procfs가 사용하는 데이터 스트럭쳐를 초기화 한다.
(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)
:VFS, VM, buffer cache 등에 대한 슬램 캐시를 만든다.
(21)
ipc_init();
#endif
:System V IPC가 지원되는 커널이라면 IPC 하부 시스템을 초기화 한다. 세마포어,
메시지큐, 공유메모리를 초기화 한다.
(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).
*/
:아키텍쳐에 따른 버그를 검사한다. 예를 들어 ia32의 "f00f 버그"다.
(23)
smp_init();
:멀티 프로세서 시스템이 가능한 아키텍쳐의 경우에만 해당하는 내용으로 SMP를 초기화.
(24)
rest_init();
:rest_init() 자체는 무척 간단하다. 우선 init 프로세스를 실행해 준다. 그리고
start_kernel()의 첫 부분에서 lock 했던 커널을 unlock 해주고 idle 상태로 들어간다.
idle 상태로 들어가도 이미 init 프로세스가 생성된 후기 때문에 상관 없이 커널의
부팅은 진행된다. idle 프로세스는 0번의 프로세스 번호를 갖는다.
}
5.7절. init()
커널의 부팅에 필요한 기본 초기화(CPU, 메모리 등)가 끝나면 init 프로세스가 만들
어지고 시스템에 존재하는 다른 하드웨어 등을 초기화 한다음 루트 디바이스를 찾아
나머지 부팅을 시작한다. init 프로세스는 1번 프로세스 번호를 갖는다.
static int init(void * unused)
{
lock_kernel();
(1)
do_basic_setup();
:여기 까지의 상태는 시스템이 이제 사용 가능한 상태까지는 왔지만 붙어 있는 다른
모든 디바이스에 대해선 초기화가 되지 않은 상태다. CPU 하부 시스템, 메모리 그리고
프로세스 관리는 동작하는 상태다. 이제 할 것은 나머지 디바이스 들을 모두 초기화
하는 일을 하는 것이다. 초기화 하는 목록은 다음과 같다. 이외에 더 있으나 중요한
것만 조금 간추렸다.
mtrr
현재는 i386에서만 존재 하는 기능으로 MTRR(Memory Type Range Register)를 말한다.
PCI나 AGP 비디오 카드를 좀더 빨리 쓸 수 있도록 해준다.
sysctrl
proc file system을 사용하도록 설정 되어 있으면 이를 초기화 해준다.
pci
PCI 시스템을 초기화 한다. PCI의 루트 디바이스를 초기화 하고 이어 PCI 버스에
연결된 모든 다른 하드웨어를 찾아 리스트에 등록한다.
isapnp
ISA 버스에 물려 있는 PnP 디바이스를 초기화한다.
socket
사용되는 프로토콜을 초기화 한다. 소켓 용 슬랩도 초기화 하고 netlink, netfileter
등도 초기화 한다.
context thread
keventd를 kernel thread로 실행한다.
pcmcia
PCMCIA 디바이스 초기화 한다.
(2)
prepare_namespace();
/*
* Ok, we have completed the initial bootup, and
* we're essentially up and running. Get rid of the
* initmem segments and start the user-mode stuff..
*/
:무엇을 어디서 마운트할 지 결정한다. 루트 디바이스를 마운트하고 램디스크를 읽어
들이는 일도 한다.
(3)
free_initmem();
unlock_kernel();
:바로 전까지 실행되면 이제 커널이 완전히 부팅한 것으로 봐도 된다. 커널 부팅에
사용된 메모리 중 필요 없는 것을 반환한다.
(4)
if (open("/dev/console", O_RDWR, 0) < 0)
printk("Warning: unable to open an initial console.\n");
(void) dup(0);
(void) dup(0);
/*
* We try each of these until one succeeds.
*
* The Bourne shell can be used instead of init if we are
* trying to recover a really broken machine.
*/
if (execute_command)
execve(execute_command,argv_init,envp_init);
:초기 콘솔을 열고 stdin, stdout, stderr을 open 한다.
(5)
execve("/sbin/init",argv_init,envp_init);
execve("/etc/init",argv_init,envp_init);
execve("/bin/init",argv_init,envp_init);
execve("/bin/sh",argv_init,envp_init);
:이제 마운트된 루트 파일 시스템에서 init를 찾아 실행해 준다.
(6)
execve("/sbin/init",argv_init,envp_init);
panic("No init found. Try passing init= option to kernel.");
:init를 찾지 못하면 여기와서 커널의 부팅이 멈춘다. 여기 까지 온다는 것은 아마도
루트 파일 시스템을 마운트하지 못했거나 루트 파일 시스템에 init가 없기 때문일 것이다.
}
5.8절. dmesg 정리
/var/log/dmesg는 부팅하는 동안 커널의 기록을 남겨 놓은 파일이다. 이 파일의 출력
을 구분지어 어느 단계에서 어떤 메시지가 출력되는지 보자.
단계를 구분지어 놓으면 start_kernel()을 분석하는데 많은 도움이 될 것이고 커널
부팅 중에 에러가 났다면 어느 단계에서 에러 났는지 범위를 좁히고 찾아내는데 많은
도움이 될 것이다.
(1) -> start_kernel()
Linux version 2.4.16 (root@halite) (gcc version 2.95.3 20010315 (release)) #22
2002. 02. 27. (수) 13:30:14 KST
(2) -> setup_memory_region()/setup_arch()/start_kerenel()
BIOS-provided physical RAM map:
BIOS-e820: 0000000000000000 - 000000000009fc00 (usable)
BIOS-e820: 000000000009fc00 - 00000000000a0000 (reserved)
BIOS-e820: 00000000000f0000 - 0000000000100000 (reserved)
BIOS-e820: 0000000000100000 - 000000001ffec000 (usable)
BIOS-e820: 000000001ffec000 - 000000001ffef000 (ACPI data)
BIOS-e820: 000000001ffef000 - 000000001ffff000 (reserved)
BIOS-e820: 000000001ffff000 - 0000000020000000 (ACPI NVS)
BIOS-e820: 00000000ffff0000 - 0000000100000000 (reserved)
(3) -> free_area_init_core()/free_area_init()/paging_init()/setup_arch()/start_kernel()
On node 0 totalpages: 131052
zone(0): 4096 pages.
zone(1): 126956 pages.
zone(2): 0 pages.
(4) -> detect_init_APIC()/init_apic_mappings()/setup_arch()/start_kernel()
Local APIC disabled by BIOS -- reenabling.
Found and enabled local APIC!
(5) -> start_kernel()
Kernel command line: BOOT_IMAGE=linux ro root=301 mem=nopentium hdd=ide-scsi
ide_setup: hdd=ide-scsi
(6) -> cpu_init()/trap_init()/start_kernel()
Initializing CPU#0
(7) -> time_init()/start_kernel()
Detected 1009.016 MHz processor.
(8) -> con_init()/console_init()/start_kernel()
Console: colour VGA+ 132x43
(9) -> calibrate_delay()/start_kernel()
Calibrating delay loop... 2011.95 BogoMIPS
(10) -> mem_init()/start_kernel()
Memory: 512920k/524208k available (1213k kernel code, 10900k reserved, 482k data, 228k init, 0k highmem)
Checking if this processor honours the WP bit even in supervisor mode... Ok.
(11) -> dcache_init()/vfs_caches_init()/start_kernel()
Dentry-cache hash table entries: 65536 (order: 7, 524288 bytes)
(12) -> inode_init()/vfs_caches_init()/start_kernel()
Inode-cache hash table entries: 32768 (order: 6, 262144 bytes)
(13) -> mnt_init()/vfs_caches_init()/start_kernel()
Mount-cache hash table entries: 8192 (order: 4, 65536 bytes)
(14) -> buffer_init()/start_kernel()
Buffer-cache hash table entries: 32768 (order: 5, 131072 bytes)
(15) -> page_cache_init()/start_kernel()
Page-cache hash table entries: 131072 (order: 7, 524288 bytes)
(16) -> identify_cpu()/check_bugs()/start_kernel()
CPU: Before vendor init, caps: 0183fbff c1c7fbff 00000000, vendor = 2
Intel machine check architecture supported.
Intel machine check reporting enabled on CPU#0.
CPU: L1 I Cache: 64K (64 bytes/line), D cache 64K (64 bytes/line)
CPU: L2 Cache: 256K (64 bytes/line)
CPU: After vendor init, caps: 0183fbff c1c7fbff 00000000 00000000
CPU: After generic, caps: 0183fbff c1c7fbff 00000000 00000000
CPU: Common caps: 0183fbff c1c7fbff 00000000 00000000
CPU: AMD Athlon(tm) Processor stepping 02
Enabling fast FPU save and restore... done.
Checking 'hlt' instruction... OK.
(17) -> start_kernel()
POSIX conformance testing by UNIFIX
(18) -> setup_local_APIC()/APIC_init_uniprocessor()/smp_init()/start_kernel()
enabled ExtINT on CPU#0
ESR value before enabling vector: 00000000
ESR value after enabling vector: 00000000
(19)-> setup_APIC_clocks()/APIC_init_uniprocessor/smp_init()/start_kernel()
Using local APIC timer interrupts.
(20) -> calibrate_APIC_clock()/setup_APIC_clocks()/APIC_init_uniprocessor/
smp_init()/ start_kernel()
calibrating APIC timer ...
..... CPU clock speed is 1009.0421 MHz.
..... host bus clock speed is 201.8084 MHz.
(21) -> setup_APIC_timer()/setup_APIC_clocks()/APIC_init_uniprocessor/
smp_init()/start_kernel()
cpu: 0, clocks: 2018084, slice: 1009042
CPU0<T0:2018080,T1:1009024,D:14,S:1009042,C:2018084>
(22) -> mtrr_setup()/mtrr_init()/do_basic_setup()/init()/rest_init()/start_kernel()
mtrr: v1.40 (20010327) Richard Gooch (rgooch@atnf.csiro.au)
mtrr: detected mtrr type: Intel
(23) -> check_pcibios()/pci_find_bios()/pcibios_config_init()/pcibios_init()/
pci_init()/ do_basic_setup()/init()/rest_init()/start_kernel()
PCI: PCI BIOS revision 2.10 entry at 0xf1180, last bus=1
(24) -> pci_check_direct()/pcibios_config_init()/pcibios_init()/pci_init()/
do_basic_setup()/init()/rest_init()/start_kernel()
PCI: Using configuration type 1
(25) -> pcibios_init()/pci_init()/do_basic_setup()/init()/rest_init()/start_kernel()
PCI: Probing PCI hardware
(26) -> pci_read_bridge_bases()/pcibios_fixup_bus()/pci_do_scan_bus()/pci_scan_bus()/
pcibios_init()/pci_init()/do_basic_setup()/init()/rest_init()/start_kernel()
Unknown bridge resource 0: assuming transparent
(27) -> pirq_find_router()/pcibios_irq_init()/ pcibios_init()/pci_init()/
do_basic_setup()/init()/rest_init()/start_kernel()
PCI: Using IRQ router VIA [1106/0686] at 00:04.0
PCI: Found IRQ 10 for device 00:0b.0
PCI: Sharing IRQ 10 with 00:11.0
PCI: Found IRQ 5 for device 00:0d.0
PCI: Sharing IRQ 5 with 00:04.2
PCI: Sharing IRQ 5 with 00:04.3
PCI: Disabling Via external APIC routing
(28) -> isapnp_init()/do_basic_setup()/init()/rest_init()/start_kernel()
isapnp: Scanning for PnP cards...
isapnp: No Plug & Play device found
(29) -> sock_init()/do_basic_setup()/init()/rest_init()/start_kernel()
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
(30) -> rtnetlink_init()/sock_init()/do_basic_setup()/init()/rest_init()/start_kernel()
Initializing RT netlink socket
(31) ->
apm: BIOS version 1.2 Flags 0x03 (Driver version 1.15)
(32) -> kswapd_init()/do_initcalls()/do_basic_setup()/init()/rest_init()/start_kernel()
Starting kswapd
JFS development version: $Name: $
(33) -> acpi_init()/do_initcalls()/do_basic_setup()/init()/rest_init()/start_kernel()
ACPI: APM is already active, exiting
(34) -> pty_init()/do_initcalls()/do_basic_setup()/init()/rest_init()/start_kernel()
pty: 256 Unix98 ptys configured
(35) -> show_serial_version()/rs_init()/do_basic_setup()/init()/rest_init()/start_kernel()
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI ISAPNP enabled
ttyS01 at 0x02f8 (irq = 3) is a 16550A
(36) -> blk_dev_init()/do_basic_setup()/init()/rest_init()/start_kernel()
block: 128 slots per queue, batch=32
(37) -> ide_init()/do_basic_setup()/init()/rest_init()/start_kernel()
Uniform Multi-Platform E-IDE driver Revision: 6.31
(38) -> ide_system_bus_speed()/ide_init()/do_basic_setup()/init()/rest_init()/start_kernel()
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx
(39) -> ide_scan_pcidev()/ide_scan_pcibus()/probe_for_hwifs()/ide_init_builtin_drivers()/
ide_init()/do_basic_setup()/init()/rest_init()/start_kernel()
VP_IDE: IDE controller on PCI bus 00 dev 21
VP_IDE: chipset revision 16
VP_IDE: not 100% native mode: will probe irqs later
VP_IDE: VIA vt82c686a (rev 22) IDE UDMA66 controller on pci00:04.1
ide0: BM-DMA at 0xd800-0xd807, BIOS settings: hda:DMA, hdb:DMA
ide1: BM-DMA at 0xd808-0xd80f, BIOS settings: hdc:DMA, hdd:DMA
(40) -> ide_setup_pci_device()/ide_scan_pcidev()/ide_scan_pcibus()/probe_for_hwifs()/
ide_init_builtin_drivers()/ide_init()/do_basic_setup()/init()/rest_init()/start_kernel()
PDC20265: IDE controller on PCI bus 00 dev 88
PCI: Found IRQ 10 for device 00:11.0
PCI: Sharing IRQ 10 with 00:0b.0
PDC20265: chipset revision 2
PDC20265: not 100% native mode: will probe irqs later
ide2: BM-DMA at 0x8000-0x8007, BIOS settings: hde:DMA, hdf:DMA
ide3: BM-DMA at 0x8008-0x800f, BIOS settings: hdg:DMA, hdh:pio
(41) -> do_identify()/actual_try_to_identify()/try_to_identify()/do_probe()/
probe_for_drive()/ probe_hwif()/ideprobe_init()/init_module()/do_basic_setup()/
init()/rest_init()/start_kernel()
hda: Maxtor 4W080H6, ATA DISK drive
hdb: IC35L040AVER07-0, ATA DISK drive
hdc: QUANTUM FIREBALLlct15 20, ATA DISK drive
hdd: LG CD-RW CED-8080B, ATAPI CD/DVD-ROM drive
(42) -> init_irq()/hwif_init()/ideprobe_init()/init_module()/do_basic_setup()/
init()/rest_init()/ start_kernel()
ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
ide1 at 0x170-0x177,0x376 on irq 15
hda: 160086528 sectors (81964 MB) w/2048KiB Cache, CHS=9964/255/63, UDMA(33)
hdb: 80418240 sectors (41174 MB) w/1916KiB Cache, CHS=5005/255/63, UDMA(33)
hdc: 39876480 sectors (20417 MB) w/418KiB Cache, CHS=39560/16/63, UDMA(33)
(43) -> check_partition()/grok_partitions()/idedisk_revalidate/init_module()/
do_basic_setup()/ init()/rest_init()/start_kernel()
Partition check:
hda: hda1 hda2
hdb: hdb1
hdc: [PTBL] [2482/255/63] hdc1 hdc2 hdc3
(44) -> config_types()/floppy_init()/do_basic_setup()/init()/rest_init()/start_kernel()
Floppy drive(s): fd0 is 1.44M
FDC 0 is a post-1991 82077
(45) -> agp_init()/do_basic_setup()/init()/rest_init()/start_kernel()
Linux agpgart interface v0.99 (c) Jeff Hartmann
agpgart: Maximum main memory to use for agp memory: 439M
agpgart: Detected Via Apollo Pro KT133 chipset
agpgart: AGP aperture is 128M @ 0xe0000000
[drm] AGP 0.99 on VIA Apollo KT133 @ 0xe0000000 128MB
[drm] Initialized mga 3.0.2 20010321 on minor 0
(46) -> init_pcmcia_cs()/do_basic_setup()/init()/rest_init()/start_kernel()
Linux Kernel Card Services 3.1.22
options: [pci] [cardbus] [pm]
(47) -> inet_init()/do_basic_setup()/init()/rest_init()/start_kernel()
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP, IGMP
IP: routing cache hash table of 4096 buckets, 32Kbytes
TCP: Hash tables configured (established 32768 bind 32768)
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
(48) -> init_pcmcia_ds()/do_basic_setup()/init()/rest_init()/start_kernel()
ds: no socket drivers loaded!
(49) -> request_module()/load_nls()/init_nls_euc_kr()/do_basic_setup()/init()/
rest_init()/start_kernel()
request_module[nls_EUC-KR]: Root fs not mounted
Unable to load NLS charset EUC-KR
(50) -> mount_root()/prepare_namespace()/init()/rest_init()/start_kernel()
VFS: Mounted root (jfs filesystem) readonly.
(51) -> free_initmem()/init()/rest_init()/start_kernel()
Freeing unused kernel memory: 228k freed
커널의 초기화 동안 등록된 드라이버들이 자동으로 실행되고 초기화 되도록 하는데,
커널을 어떻게 설정하는가에 따라 커널에 포함되는 것이 다르므로 일일히 기록하는
대신에 자동으로 커널 컴파일하는 동안 포함되도록 할 수 있다. 필요한 모듈에
__init란 속성을 사용하고 module_init()를 사용해 이런 일이 가능하도록 한다.
module_init()는 include/linux/init.h에 다음과 같이 정의되어 있다.
#define module_init(x) __initcall(x);
__initcall(x)는 module로 지정됐는가 아닌가에 따라 정의가 달라지는데 어찌됐든
.initcall.init란 섹션에 속하게 된다. 여기에 속하면 커널의 링킹 동안 모아진
.initcall.init가 do_basic_setup() 혹은 do_initcalls()에 의해 자동으로 불려지게
된다(vmlinux.lds를 보면 .initcall.init를 모아주는 부분이 있다).
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
참조 사이트 :http://61.96.198.114/남상규씨 홈페이지
http://kelp.or.kr
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[이 게시물은 withyou님에 의해 2005-02-06 17:13:16 자료실(으)로 부터 이동됨]
[이 게시물은 withyou님에 의해 2005-02-06 17:22:48 test(으)로 부터 이동됨]
댓글