Linux is the first program that runs when the system boots.
Linux begins at init/main.c/start_kernel().
Linux uses printk
(not โprintfโ) to display messages.
All booting messages are displayed by Linux with printk
and you can find the corresponding Linux code that prints each boot message.
All boot messages are stored in the kernel buffer and you can display this buffer with dmesg
command.
Find Linux code that prints the first boot message.
https://www.virtualbox.org/wiki/Downloads
If you have an error, run VirutalBox as administrator and try again. For USB error, simply disable usb controller in โSettingโ tab. For Hyper-V error (Raw-mode is unavailable), turn off Hyper-V feature in control panel>program and feature>window feature. Select My Linux. Login as root and hit Enter for the password prompt. If VirtualBox still cannot open the session, you need to look at the log file (right click on Gentoo VM and select โlog fileโ) and see what is the error and fix it. (In some cases, you may need to download and install virtualbox extension package.)
main.c
main.c๋ init ํด๋์ ์์ผ๋ฉฐ ๋ฆฌ๋ ์ค์ ์์์ ์ด๋ค. start_kernel() ํจ์๋ main.c์ ์์นํ๋ค.
fork.c
fork.c๋ kernel ํด๋์ ์์ผ๋ฉฐ ์ด ํด๋์๋ ํ๋ก์ธ์ค์ ๊ด๋ จ๋ ํ์ผ์ด ์๋ค.
entry_32.S
find / -name entry_32.S -type f
find
๋ช
๋ น์ด๋ฅผ ํตํด entry_32.S์ ์์น๋ฅผ ์ฐพ์๋ณด๋ฉด
entry_32.S๋ โarch/x86/kernelโ์ โarch/powerpc/kernelโ์ ์๋ค. ์ด ์ค โx86โ ํด๋์๋ ์ํคํ
์ฒ๋ง๋ค ๋ค๋ฅด๊ฒ ๋์ํ๋ ํจ์๋ค์ด ๋ด๊ฒจ์์ผ๋ฉฐ โx86โ์ ์ธํ
์ 32๋นํธ ์ํคํ
์ฒ๋ฅผ ์๋ฏธํ๋ค.
To find a string โstart_kernelโ, go to the linux top directory (linux-2.6.25.10) and do
$ grep -nr "start_kernel" * | more
Use "space"
to move down the screen, q
to exit
Once you found the file that has โstart_kernelโ, use vi
to read the file.
In vi, type /start_kernel
to search for the first instance of โstart_kernelโ.
For the next string, simply type โ/โ. Repeat โ/โ until you find the start_kernel()
function.
Use โjโ to mode down the cursor, โkโ to move up, โ^fโ to move one screen down, โ^bโ to move
up one screen up.
start_kernel()
is the first C function run by Linux. start_kernel()
. printk()
(not printf
) is the function to print something in the kernel. dmesg > x
and vi x
. dmesg > x
will send the booting message to file x
. vi x
you can look at the file x
.start_kernel()
ํจ์์ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ๋ค.
์ด ์ค ๊ฐ์ฅ ๋จผ์ printk
๊ฐ ์ฌ์ฉ๋ ๋ถ๋ถ์ ์๋์ ๊ฐ๋ค.
printk(KERNEL_NOTICE);
printk(linux_banner);
์ฒซ ๋ฒ์งธ ์ถ๋ ฅ์ ์ ๋ ํจ์ ํธ์ถ๋ก KERN_NOTICE
๋ ์ถ๋ ฅ์ ๋ก๊ทธ ๋ ๋ฒจ์ ์ค์ ํ๋ ๊ธฐํธ๋ก ๋ค์ ์ถ๋ ฅ์ด ์ ์์ ์ธ ์ ๋ณด์ ํด๋นํ๋ ๋ก๊ทธ์์ ๋ํ๋ธ๋ค. ๊ทธ๋ ๋ค๋ฉด linux_banner
๊ฐ ์ง์ง ์ถ๋ ฅ์ธ๋ฐ ํด๋น ๊ฐ์ด ์ ์๋ init/version.c
์ผ๋ก ๊ฐ๋ฉด ์๋์ ๊ฐ์ด ๋ฆฌ๋
์ค์ ๋ฒ์ ๊ณผ ์ปดํ์ผ ํ๊ฒฝ์ ์ถ๋ ฅํ๋ ๋ฌธ์์ด์ด ๊ตฌ์ฑ๋์ด ์๋ค.
init/version.c:
/* FIXED STRINGS! Don't touch! */
const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
๋ฐ๋ผ์ ๋ฆฌ๋ ์ค๊ฐ ๋ถํ ๋๋ฉด ๋ฆฌ๋ ์ค์ ๋ฒ์ ๊ณผ ์ปดํ์ผ ํ๊ฒฝ์ด ๊ฐ์ฅ ๋จผ์ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
dmesg > x
๋ฅผ ํตํด ๋ถํ
๋ฉ์ธ์ง๋ฅผ ํ์ธํด๋ณธ ๊ฒฐ๊ณผ๋ ์๋์ ๊ฐ๋ค.
๋ฆฌ๋ ์ค ๋ฒ์ ๊ณผ GCC ์ ๋ณด๊ฐ ๊ฐ์ฅ ๋จผ์ ์ถ๋ ฅ๋๋ค.
trap_init()
$ grep -nr "trap_init" * | more
linux-2.6.25.10/arch/x86/
์์ ์ ๋ช
๋ น์ด๋ก โtrap_initโ์ ์ฐพ์๋ณด์๋ค.
arch/x86/kernel/traps_64.c:1127
์ arch/x86/kernel/traps_32.c:1140
์์ void __init trap_init(void)
๊ฐ ์ฌ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
$ vi kernel/traps_32.c
์ ๋ช
๋ น์ด๋ฅผ ํตํด traps_32.c
ํ์ผ์ trap_init(void)
ํจ์๋ฅผ ์ดํด๋ณด์๋ค.
set_trap_gate(0,÷_error);
set_intr_gate(1,&debug);
set_intr_gate(2,&nmi);
set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
set_system_gate(4,&overflow);
set_trap_gate(5,&bounds);
set_trap_gate(6,&invalid_op);
set_trap_gate(7,&device_not_available);
set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
set_trap_gate(9,&coprocessor_segment_overrun);
set_trap_gate(10,&invalid_TSS);
set_trap_gate(11,&segment_not_present);
set_trap_gate(12,&stack_segment);
set_trap_gate(13,&general_protection);
set_intr_gate(14,&page_fault);
set_trap_gate(15,&spurious_interrupt_bug);
set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check);
trap_init()
ํจ์์๋ ์์ ๊ฐ์ด set ํจ์๊ฐ ๋์ด๋์ด ์๋ค. ์ด๊ฒ์ผ๋ก ์ ์ถํด๋ณธ๋ค๋ฉด, ์์คํ
์ฝ์ ์ํ ์
ํ
์ด ์ด๋ฃจ์ด์ง๋ ๊ฒ ๊ฐ๋ค.
init_IRQ()
$ grep -nr "init_IRQ" * | more
linux-2.6.25.10/arch/x86/
์์ ์ ๋ช
๋ น์ด๋ก โinit_IRQโ์ ์ฐพ์๋ณด์๋ค.
arch/x86/kernel/paravirt.c:167
์์ void init_IRQ(void)
๊ฐ ์ฌ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
$ vi kernel/paravirt.c
$ vi kernel/i8259_64.c
i8259_64.c
์ native_init_IRQ(void)
ํจ์์
...
set_intr_gate(vector, interrupt[i]);
...
๋ฅผ ๋ณด๋ฉด, interrupt gate๋ฅผ ์ด๊ธฐํํ๋ ๊ฒ์ผ๋ก ์ ์ถํด๋ณผ ์ ์๋ค.
IRQ๋ Interrupt ReQuest์ ์ฝ์๋ก, ์ธํฐ๋ฝํธ ์ ํธ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ์ ์ฐ์ด๋ ์ปดํจํฐ ๋ฒ์ค ๋ผ์ธ์ ์ธํฐ๋ฝํธ ๋์์ ๋งํ๋ค.
init_IRQ()
๋ ์ปค๋ interrupt subsystem์ ํ๋์จ์ด ์ผ๋ถ๋ฅผ ์ด๊ธฐํํ๋ ๊ฒ์ผ๋ก ์ ์ถํ ์ ์๋ค.
sched_init()
$ grep -nr "sched_init(void)" *
linux-2.6.25.10/
์์ ์ ๋ช
๋ น์ด๋ก โsched_initโ์ ์ฐพ์๋ณด์๋ค.
kernel/sched.c:7261
์์ void __init sched_init(void)
๊ฐ ์ฌ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
$ vi kernel/sched.c
sched_init(void)
๋ init task๊ฐ ์ฌ์ฉํ๋ CPU ๋ฒํธ๋ฅผ ํ ๋นํ๊ณ PID HASH TABLE์ ์ด๊ธฐํํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ปค๋์ ๋ด๋ถ ํ์ด๋จธ๊ฐ ์ฌ์ฉํ๋ ๋ฒกํฐ ๋ฐ bottom-half handler๋ฅผ ์ด๊ธฐํํ๋ค.
time_init()
$ grep -nr "time_init(void)" *
linux-2.6.25.10/arch/x86/
์์ ์ ๋ช
๋ น์ด๋ก โtime_initโ์ ์ฐพ์๋ณด์๋ค.
arch/x86/kernel/time_32.c:135
์ arch/x86/kernel/time_64.c:117
์์ void __init time_init(void)
๊ฐ ์ฌ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
$ vi kernel/time_32.c
$ grep -nr "tsc_init" *
$ vi kernel/tsc_32.c
CMOS์์ ์๊ฐ์ ์ฝ๊ณ CPU์ ์๋๋ฅผ ์ป์ด๋ด๋ ๊ฒ์ผ๋ก ์ถ์ธกํ ์ ์๋ค.
console_init()
$ grep -nr "__init console_init(void)" *
linux-2.6.25.10/
์์ ์ ๋ช
๋ น์ด๋ก โconsole_initโ์ ์ฐพ์๋ณด์๋ค.
drivers/char/tty_io.c:4037
์ void __init console_init(void)
ํจ์๊ฐ ์ฌ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
$ vi drivers/char/tty_io.c
์ปค๋์ ์ง๋ ฌ ์ฝ์ ๋๋ฐ์ด์ค๊ฐ ์ฌ์ฉํ๋๋ก ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ ์ด๊ธฐํ๋ฅผ ์ํํ๋ค.
mem_init()
$ grep -nr "mem_init" *
linux-2.6.25.10/
์์ ์ ๋ช
๋ น์ด๋ก โmem_initโ์ ์ฐพ์๋ณด์๋ค.
arch/x86/mm/init_64.c:511
์ arch/x86/mm/init_32.c:569
์์ void __init mem_init(void)
๊ฐ ์ฌ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
$ vi mm/init_32.c
์ ๋ช
๋ น์ด๋ฅผ ํตํด init_32.c
ํ์ผ์ void __init mem_init(void)
ํจ์๋ฅผ ์ดํด๋ณด์๋ค.
์ปค๋์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์๋ธ ์์คํ ์ ์ด๊ธฐํ๋ฅผ ๋ด๋นํ๋ ํจ์๋ก ์์ธกํ ์ ์๋ค.
rest_init()
$ grep -nr "rest_init" *
linux-2.6.25.10/
์์ ์ ๋ช
๋ น์ด๋ก โrest_initโ์ ์ฐพ์๋ณด์๋ค.
rest_init()
ํจ์๋ linux-2.6.25.10/init/main.c
์ ์์นํ ๊ฒ์ ํ์ธํ ์ ์๋ค.
$ vi init/main.c
์ ๋ช
๋ น์ด๋ฅผ ํตํด main.c
ํ์ผ์ rest_init(void)
ํจ์๋ฅผ ์ดํด๋ณด์๋ค.
์ด๊ธฐํ ๊ธฐ๋ฅ์ ์ฌ์ฉ๋๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ ํ ์ปค๋ thread๋ก init()
์ ์์ํ์ฌ ์ปค๋ ๋ถํ
์ ์๋ฃํ๋ค.
printf
printf
๋ ์ ์ ๋ชจ๋์์๋ง ํธ์ถ์ด ๊ฐ๋ฅํ๋ค.printf
ํจ์์ ๊ฒฝ์ฐ ๋ด๋ถ์ ์ผ๋ก ๋ฒํผ์ ์ถ๋ ฅํ ๊ฒ์ ๋ชจ์๋์๋ค๊ฐ ๋ฐฉ์ถ์ํจ๋ค.printk
printk
๋ OS ๋์ ์ค์ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ ์ฉ๋์ด๋ฉฐ ์ปค๋๋ชจ๋์์๋ง ํธ์ถ์ด ๊ฐ๋ฅํ๋ค.printk
๋ ๋ฒํผ์์ด ๋ฐ๋ก ์ถ๋ ฅํ๋ค.printf
๋ณด๋ค ๊ฐ๋ณ๊ฒ ๋์ํ๋ printk
๋ฅผ ์ด์ฉํ๋ค.printk
๋ฅผ ์ด์ฉํ๋ค.