ThaiCERT: Thai Computer Emergency Response Team
ศูนย์ประสานงานการรักษาความปลอดภัยคอมพิวเตอร์ ประเทศไทย 
 
 
 



ชื่อเรื่อง : System Bootup and Shutdown Process
เรียบเรียงโดย : ภูวดล ด่านระหาญ
เรียบเรียงเมื่อ : 10 กันยายน 2545

กล่าวนำ
เอกสารฉบับนี้จะอธิบายขั้นตอนการบูตของลินุกซ์ในระบบที่ใช้สถาปัตยกรรมแบบ x86 ที่ติดตั้ง LILO เป็น boot loader ทั้งนี้จะใช้ Red Hat Linux เป็นระบบปฏิบัติการหลักในการนำเสนอ โดยมีจุดประสงค์เพื่อให้ผู้ดูแลระบบสามารถเข้าใจกระบวนการทำงานทั้งหมดได้อย่างถูกต้อง

ขั้นตอนการบูต
ขั้นตอนการบูตที่จะกล่าวถึงต่อไปนี้ เป็นของระบบที่ใช้สถาปัตยกรรมแบบ x86 ภายหลังจากที่ระบบโหลดเคอร์เนล (kernel) ได้แล้ว ขั้นตอนการบูตของ Red Hat Linux ก็จะเหมือนกันในทุกๆ สถาปัตยกรรม


รูปที่ 1 แสดงกระบวนการบูตใน x86 ที่ใช้ LILO เป็น boot loader

เมื่อเครื่องคอมพิวเตอร์ถูกเปิดขึ้นมา หน่วยประมวลผลหลัก (processor) จะโหลดและรัน BIOS ซึ่งเก็บไว้ใน ROM (Read Only Memory) ขึ้นมา จากนั้น BIOS จะทำการตรวจสอบระบบ ค้นหาอุปกรณ์ที่ต่อเชื่อมกับเครื่องคอมพิวเตอร์พร้อมทั้งตรวจสอบ แล้วจึงจะค้นหาอุปกรณ์ที่มีหน้าที่ในการบูตระบบ โดยปกติแล้วมันจะค้นหาฟลอปปี้ดิสก์ ซีดีรอม ที่สามารถบูตได้ จากนั้นจึงจะค้นหาฮาร์ดดิสก์ต่อไป อย่างไรก็ตามใน BIOS รุ่นใหม่ๆ ผู้ใช้สามารถกำหนดลำดับของการเลือกอุปกรณ์ที่จะใช้บูตผ่านทาง BIOS ได้

ก่อนที่จะอธิบายถึงลำดับการบูตต่อไป จำเป็นต้องอธิบายถึงลักษณะของฮาร์ดดิสก์ซักเล็กน้อยเพื่อให้รู้จักและเข้าใจกลไกการทำงาน ซึ่งเกี่ยวเนื่องกับกลไกการบูตของลินุกซ์ต่อไป

โดยปกติในฮาร์ดดิสก์หนึ่งตัวจะมีข้อมูล 512 ไบต์แรกหรือเซกเตอร์แรกของฮาร์ดดิสก์ (โดยปกติ 1 เซกเตอร์เท่ากับ 512 ไบต์) บรรจุข้อมูลส่วนที่สำคัญที่สุด เรียกว่า Master Boot Record (MBR) โดยใน MBR นี้จะมีโปรแกรมของ boot loader บรรจุไว้อยู่ซึ่งจะมีข้อมูลรายละเอียดของพาร์ทิชัน รวมทั้งโค้ดในการส่งผ่านการทำงานให้เคอร์เนล (ในแต่ละพาร์ทิชันจะมี boot sector แยกเป็นของตัวเองต่างหาก ตัว boot loader เป็นเพียงตัวทำหน้าที่แสดงผลให้ผู้ใช้เลือกและส่งต่อกระบวนการบูตไปให้กับโปรแกรมในส่วน boot sector)

สำหรับตัว boot loader นั้น สามารถเลือกได้ว่าจะใช้ตัวใด ซึ่งจะแยกตามชนิดของ architecture ของฮาร์ดแวร์ เช่น

ซึ่งในกระบวนการติดตั้ง Red Hat Linux จะมีช่วงหนึ่งที่ให้ผู้ติดตั้งเลือกได้ว่าจะเลือกใช้ boot loader ตัวใด ใน Red Hat 7.2 ขึ้นไป หากติดตั้งบน x86 ก็จะเลือกได้ระหว่าง LILO หรือ GRUB ในที่นี้ขอเลือกใช้ LILO เป็นตัวอย่าง เพราะมี configuration ที่ง่ายและไม่ซับซ้อน ในขณะที่ GRUB นั้นเป็น boot loader ที่เผยแพร่ออกมาภายหลังจึงมี feature ในการใช้งานที่ดีกว่าและซับซ้อนกว่า LILO เช่น ไม่จำเป็นต้องเขียนทับ MBR ทุกครั้งที่มีการเปลี่ยนแปลง configuration ของ GRUB เพราะ GRUB สามารถอ่านข้อมูล configuration จากดิสก์ได้โดยตรง ในขณะที่ LILO ยังต้องเขียนทับ MBR ทุกครั้งที่มีการเปลี่ยนแปลง configuration อย่างไรก็ตามการเลือก boot loader นั้นควรเลือกตัวที่ผู้ติดตั้งมีความเข้าใจใน boot loader ตัวนั้นแล้วซึ่งจะสามารถแก้ปัญหาที่เกิดขึ้นได้ เช่น แก้ไข configuration ของ boot loader เองได้

กลับเข้าสู่กระบวนการบูตกันต่อ ภายหลังจากที่ BIOS สามารถเลือกได้ว่าจะบูตจาก boot device ตัวใด และในกรณีที่บูตจากฮาร์ดดิสก์ ตัว BIOS จะทำการโหลด LILO จาก MBR (หรือ boot loader ตัวอื่นที่เลือกไว้) และรัน LILO ขึ้นมาพร้อมกับส่งต่อกระบวนการบูตให้แก่ LILO โดย LILO จะแสดง prompt ให้ผู้ใช้สามารถเลือกได้ว่าจะบูตจากระบบปฏิบัติการใด (ขึ้นกับการตั้งค่าในไฟล์ /etc/lilo.conf) ซึ่งภายใต้การแสดงผลดังกล่าว LILO จะมีข้อมูลอยู่แล้วว่าระบบปฏิบัติการใดถูกติดตั้งบนพาร์ทิชันใด หากผู้ใช้ไม่ได้เลือกว่าจะบูตจากระบบปฏิบัติการใดหรือเคอร์เนลเวอร์ชันใดภายในเวลาที่ระบุไว้ ตัว LILO เองก็จะทำการบูตจากเคอร์เนลที่เป็นดีฟอลต์โดยอัตโนมัติ

ภายหลังจากที่ LILO เลือกได้ว่าจะทำการบูตจากพาร์ทิชันใดแล้ว มันจะทำการโหลดเคอร์เนลขึ้นสู่หน่วยความจำและเคอร์เนลจะทำหน้าที่ควบคุมการบูตต่อไป ซึ่งสามารถอธิบายได้ดังนี้

รายละเอียดการทำงานของ init
init เป็นโพรเซสแรกที่เริ่มทำงานเมื่อถูกบูตขึ้นมา ดังนั้นมันจะได้รับ process id เป็น 1 ซึ่งจะกลายเป็น parent, grandparent process ของโพรเซสอื่นๆ ด้วย


รูปที่ 3 แสดงลำดับของโพรเซสเมื่อใช้คำสั่ง pstree

ทั้งนี้ init จะอ่านข้อมูล configuration จาก /etc/inittab และยังอ่านไฟล์นี้เมื่อทำการ shutdown ระบบอีกด้วย โดยข้อมูลในไฟล์ /etc/inittab จะเป็นตัวบอกว่าลินุกซ์จะเริ่มต้นการทำงานอย่างไร รวมทั้งเป็นตัวจัดการรันสคริปต์ต่างๆ เพื่อเตรียมความพร้อมในการทำงานด้วย

รูปแบบของ configuration option ในไฟล์ /etc/inittab จะมีลักษณะดังนี้คือ

id:runlevel:action:process arguments

สำหรับ run level ใน Red Hat Linux นั้น สามารถอธิบายได้ดังตารางที่ 1


ตารางที่ 1 แสดง run lvel และคำอธิบาย
Run Level คำอธิบาย
0 Halt - ใช้หยุดการทำงานของระบบ
1 Single user - จะโหลด configuration น้อยที่สุด เพื่อให้ใช้งานได้คนเดียวเท่านั้น
2 ไม่ได้ใช้งาน
3 Multiuser
4 ไม่ได้ใช้งาน
5 X Window - เป็นกราฟฟิกโหมด
6 Reboot - ใช้รีบูตระบบ
S หรือ s ถูกใช้งานโดยสคริปต์ที่รันใน level 1
a, b, c เป็น run level พิเศษ ซึ่งปกติไม่ได้ใช้งาน

ส่วน action นั้น สามารถอธิบายได้ด้วยตารางที่ 2

ตารางที่ 2 แสดง action ที่ใช้งานได้ในไฟล์ /etc/inittab และคำอธิบาย
Action คำอธิบาย
respawn รันโพรเซสใหม่ทุกครั้งเมื่อโพรเซสหยุดการทำงาน
wait รันโพรเซสเพียงครั้งเดียว และให้ init รอจนกระทั่งโพรเซสสิ้นสุดการทำงาน
once รันโพรเซสเพียงครั้งเดียว
boot โพรเซสนี้รันในขณะบูต และให้ init ไม่สนใจค่าในส่วน id field
bootwait โพรเซสนี้รันในขณะบูต และให้ init รอจนโพรเซสสิ้นสุดการทำงาน
off จะไม่ทำการรันโพรเซสที่ระบุในบรรทัดนี้ เหมือนกับเป็นการ disable (คำแนะนำ: ควรใช้เครื่องหมาย # ใส่ไว้ที่ต้นบรรทัดจะดีกว่า)
ondemand รันโพรเซสเมื่อมีการระบุ run level เป็น a, b หรือ c (ปกติไม่ได้ใช้งาน)
initdefault ตั้งค่า run level ที่ระบุเป็น default run level
sysinit โพรเซสนี้จะถูกรันเพียงครั้งเดียวในขณะบูต (มี precedence สูงกว่า boot และ bootwait)
powerwait โพรเซสจะถูกรันเมื่อได้รับสัญญาณ SIGPWR จาก UPS software โดย init จะรอจนกระทั่งโพรเซสสิ้นสุดการทำงาน
pawerfail คล้ายกับ powerwait เพียงแต่ init จะไม่รอจนกระทั่งโพรเซสสิ้นสุดการทำงาน
powerokwait โพรเซสจะถูกรันเมื่อได้รับสัญญาณ SIGPWR และมีคำว่า OK ในไฟล์ /etc/powerstatus โดยปกติเหตุการณ์นี้จะเกิดขึ้นเมื่อ UPS software แจ้งมาว่าเหตุการณ์ได้กลับสู่สภาวะปกติแล้ว
ctrlaltdel โพรเซสนี้จะถูกเมื่อได้รับสัญญาณ SIGINT
kbrequest โพรเซสนี้จะถูกเมื่อได้รับ KeyboardSignal จาก keyboard handler

เริ่มต้นที่บรรทัดแรกๆ ของไฟล์ /etc/inittab จะพบบรรทัดดังตัวอย่างด้านล่าง

id:3:initdefault:

จากบรรทัดด้านบน เป็นคำสั่งที่ทำให้ระบบทำงานใน run level 3 ซึ่งเป็น multiuser mode โดยปกติหากติดตั้ง X Window ด้วย จะมี run level ที่เป็นดีฟอลต์คือ 5 อย่างไรก็ตามผู้ดูแลระบบสามารถแก้ไขค่านี้ให้เป็น run level ที่ต้องการได้

จากนั้น init จะทำการ initialise ระบบตามที่ระบุไว้ในสคริปต์ /etc/rc.d/rc.sysinit

# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit

โดย rc.sysinit มีฟังก์ชันการทำงานดังนี้

จากนั้นลินุกซ์จะทำการรันสคริปต์ภายใต้โฟลเดอร์ /etc/rc.d/rc ตามด้วย option คือ level ที่ระบุ ดัง configuration ใน /etc/inittab

l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6

เช่นเมื่อถูกสั่งให้รันใน run level 3 สคริปต์ rc จะทำการตรวจสอบว่าไดเรกทอรี /etc/rc.d/rc3.d มีไฟล์อยู่หรือไม่ หากมีอยู่ก็จะทำงานโดย จะรันสคริปต์ที่อยู่ภายใต้/etc/rc.d/rc3.d/ และมีชื่อไฟล์ขึ้นต้นด้วยตัวอักษร S (uppercase) โดยจะส่งคำสั่งไปยังสคริปต์ดังกล่าวด้วยออปชัน start

ซึ่งผู้ใช้สามารถเปลี่ยนลำดับการทำงานก่อนหลังได้โดย เปลี่ยนค่าตัวเลขที่อยู่หลังตัวอักษร S หรือ K เช่น ไฟล์ S85httpd จะถูกสั่งให้ทำงานก่อนไฟล์ S90mysql ซึ่งหากต้องการให้ mysql ถูก start ก่อนก็สามารถเปลี่ยนชื่อไฟล์จาก S90mysql เป็นตัวเลขอื่นที่น้อยกว่า 85 และไม่ซ้ำกับไฟล์อื่นที่มีอยู่ในไดเรกทอรีเดียวกัน

จากนั้น init จะทำการรันไฟล์ /etc/rc.local ซึ่งถูกรันเมื่อระบบถูกบูตหรือรันใน run level 2,3 หรือ 5 โดยปกติมักจะใช้เพื่อใส่คำสั่งที่ต้องการให้ทำงานในการบูตแต่ละครั้ง และท้ายสุดก็จะรันสคริปต์ในไฟล์ /etc/rc.serial โดยปกติแล้วจะรันเมื่อสิ้นสุดกระบวนการใน run level 1 หรือ 3 เพื่อทำหน้าที่เริ่มต้นการทำงานของ serial port

ตัวอย่างการแก้ไข /etc/inittab
มีค่า configuration ที่ผู้ดูแลระบบอาจจะพิจารณาแก้ไขในไฟล์ /etc/inittab คือ

# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now

ซึ่งเป็นตัวที่สั่งให้รีบูตระบบเมื่อผู้ใช้กดปุ่ม ctrl-alt-del พร้อมกัน ซึ่งหากตั้งไว้ตามค่าดีฟอลต์ก็อาจจะเป็นผลเสียเมื่อมีผู้ไม่ประสงค์ดีที่สามารถเข้าถึงคอนโซลและสามารถใช้แป้นพิมพ์ได้ก็จะสามารถรีบูตระบบได้โดยไม่ต้องล็อกอิน ซึ่งก็ขึ้นอยู่กับวิจารณญาณของผู้ดูแลระบบว่าจะใช้ความสามารถนี้หรือไม่


การชัตดาวน์ระบบ
กระบวนการชัตดาวน์มีความสำคัญต่อระบบลินุกซ์เป็นอย่างยิ่ง เพราะหากข้ามขั้นตอนหรือใช้คำสั่งผิดก็อาจจะทำให้เกิดความเสียหายต่อ file system ได้ ทั้งนี้เพราะ linux ทำงานโดยดึงข้อมูลจาก cache ซึ่งจะเก็บข้อมูลลงดิสก์เป็นช่วงเวลา หากเครื่องคอมพิวเตอร์ถูกปิดเครื่องไปโดยตรงก็อาจจะทำให้ข้อมูลใน cache ไม่ถูกบันทึกลงในไฟล์ซึ่งอาจจะทำให้ไฟล์มีปัญหาได้

นอกจากนี้ลินุกซ์ยังเป็นระบบปฏิบัติการที่เป็น multitask ซึ่งหากทำการ shutdown อย่างผิดขั้นตอน เช่น การกดปุ่มสวิตช์ power off โดยตรง เป็นต้น อาจจะส่งผลให้โพรเซสหลายๆ ตัวซึ่งทำงานใน background mode สูญเสียข้อมูล ซึ่งอาจจะเกิดความเสียหายต่อระบบได้

ก่อนทำการ shutdown ผู้ดูแลระบบจะต้องปิดการทำงานของโปรแกรมต่างๆ ที่รันอยู่ และใช้คำสั่ง shutdown ซึ่งจะส่งข้อความแจ้งเตือนไปยังผู้ใช้ที่ล็อกอินอยู่ในระบบให้ทราบว่า เครื่องกำลังจะ shutdown และแจ้งให้ผู้ใช้ทำการปิดการทำงานของโปรแกรมที่ใช้อยู่ พร้อมทั้งล็อกเอาต์ออกจากระบบ

คำสั่งที่ใช้ในการชัตดาวน์ระบบคือ /sbin/shutdown ซึ่งสามารถใช้ได้หลายรูปแบบ เช่น

เมื่อระบบถึงเวลาที่ต้องชัตดาวน์จริงๆ file system ทุกแห่งจะถูก unmount (ยกเว้น root) พร้อมกับ kill user process ทิ้งไป, ชัตดาวน์ daemon, file system ทุกที่จะถูก unmount และทุกสิ่งก็จะหยุดการทำงานโดยสิ้นเชิง

มีคำสั่งที่สามารถใช้ชัตดาวน์ระบบ เช่นเดียวกับคำสั่ง shutdown คือคำสั่ง init 0 และ halt ซึ่งทั้งสองคำสั่งให้ผลเช่นเดียวกันกับ shutdown แต่ควรใช้คำสั่ง shutdown จะดีกว่าเพราะมีส่วนของการเตือนผู้ใช้ที่ยังล็อกออนอยู่ในระบบก่อนที่จะชัตดาวน์จริง

การรีบูตระบบ
การรีบูตระบบสามารถทำได้โดยใช้คำสั่ง shutdown -r now หรือ init 6 นอกเหนือจากการพิมพ์คำสั่งแล้ว หากไม่มีการแก้ไขค่าดีฟอลต์ใน /etc/inittab ผู้ใช้ยังสามารถกดปุ่ม ctrl-alt-del พร้อมกันเพื่อรีบูตระบบได้อีกด้วย



Home || เอกสารเผยแพร่ || Unix & Linux

ThaiCERT Disclaimer | Copyright © 2001 ThaiCERT(NECTEC). All rights reserved.