[Quan trọng] Booting Linux - GRUB - Loading Kernel - Init - Runlevel


BOOTING
- Khi nhấn Power on, BIOS sẽ khởi chạy quá trình POST máy - khởi động và tự kiểm tra phần cứng, nếu OK thì sẽ có tiếng bip, còn không thì sẽ là những tiếp bip bất thường báo lỗi hoặc có khi im luôn.
- Quá trình POST xong, BIOS sẽ đọc trong cấu hình của mình để biết khởi động từ thiết bị nào (thường bạn hay nhấn F2, DEL, F10,... để vào BIOS cài đặt các phần này hoặc vào giao diện để chọn thiết bị khởi động - thực chất cũng là cấu hình BIOS). BIOS sẽ đọc và tải vào RAM sector đầu tiên của thiết bị khởi động, sau đây ta xét HDD, và sector đầu tiên trên HDD là MBR. MBR được tạo khi phân vùng ổ cứng nhưng là sector nằm ngoài các partition này (khác các boot sector - là sector đầu tiên của primary partition).
- Thông thường, MBR làm nhiệm vụ tải boot sector của partition được đánh dấu là active vào RAM để thực thi, sau đó boot sector tải boot loader vào RAM. Nhưng với Linux, MBR không đả động đến boot sector của active partition, nó tải luôn boot loader trên một non-active partition vào RAM.
- Boot loader mặc định của CentOS 6 là GRUB. MBR sẽ tải GRUB vào RAM.
- Sau đó, GRUB tải nhân Linux và ramdisk vào RAM.
- Nhân Linux sẽ thực thi chương trình init và init sẽ lo liệu nốt các công việc còn lại.

GRUB
Grub là 1 boot loader và là mặc định của Linux. Nó cho phép người dùng lựa chọn hệ điều hành và cách khởi động. Bạn có thể bấm phím “e” để thấy ẩn dưới mỗi lựa chọn hệ điều hành là các lệnh tải nhân hệ điều hành đó, có thể sửa lại các lệnh này. Hoặc bấm “c” để về command line interface (thường được gọi là GRUB shell) tại dấu nhắc người dùng có thể tự gõ các lệnh tải nhân hệ điều hành. Để ngăn người lạ tự gõ các lệnh này, GRUB có thể bị đặt password. Lúc đó không có lựa chọn “e” hay “c” nữa mà chỉ có lựa chọn “p” để người dùng gõ password vào xác nhận.
Grub được thiết kế cho để có thể load đa hệ điều hành. Nhưng nó chỉ load được trực tiếp các loại hệ điều hành UNIX like, với các HĐH khác (Windows, OS/2,...) thì Grub chỉ có thể load gián tiếp qua cơ chế chainloader., để tai boot loader cho các HĐH này.
1. Tải Grub:
Khi vào Grub ta sẽ thấy 1 giao diện lựa chọn HĐH, gồm 1 cái ảnh nền, 1 khung danh sách các HĐH khả dụng. Grub cũng phải thực hiện quá trình nhận diện HDD, primary partition, root path, đọc và hiển thị kernel,... Rõ ràng Grub làm nhiều việc và cần mã nguồn đủ lớn để lưu giữ các thông tin trên.
Nhưng như lúc đầu ta đã nói, Grub phải được đặt trên MBR (với Linux) hoặc trên boot sector của active partition (với non-Linux) chỉ vọn vẹn 512 B. Vậy làm sao để nó đảm nhận nhiều việc như vậy ?
Thực tế GRUB được chia làm 2 (hoặc 3) phần là stage 1 và stage 2 (hoặc thêm stage 1.5). Chỉ stage 1 được lưu ở MBR hoặc bootsector, sau khi stage 1 được tải nó sẽ tải stage 2 (hoặc tải stage 1.5 rồi stage 1.5 sẽ tải stage 2) như vậy GRUB được tải lần lượt từng phần:
    a. Grub stage 1
Stage này rất nhỏ và được nhúng vào MBR hay boot sector, khi stage này được chạy, nó sẽ triệu gọi stage 2 (là file /boot/grub/stage2).
Tuy nhiên để có thể triệu gọi file stage 2, stage 1 cần hiểu file system mới có thể "dò ra" đường dẫn stage 2 (vì lúc này Linux chưa khởi động nên Grub phải tự làm tất cả), nhưng để hiểu file system thì 1 sector không thể đủ để chứa các thông tin cần thiết. Stage 1 chỉ có thể lưu địa chỉ vật lý của stage 2 (CHS) nhưng địa chỉ vật lý rất dễ bị thay đổi.
Vậy giải pháp là Grub sẽ có 1 vùng đệm lưu đường dẫn đến stage 2 và lưu thông tin để Grub hiểu các file system, ta gọi là stage 1.5
     b. Grub stage 1.5
Thực ra nếu ta chọn cài Grub tại MBR thì mới có stage 1.5, nếu ta cài Grub tại boot sector thì sẽ không có stage này.
Vị trí của stage 1.5 nằm ở sector thứ 2 của ổ cứng, ngay sau MBR đến sector thứ 16 (sector đầu tiên của partition đầu tiên của HDD là sector thứ 64 - nghĩa là có 1 khoảng trống giữa MBR và partition). Stage 1.5 có khả năng hiểu các filesystem ext2, fat, ffs, reiserfs, vstafs, … trên HDD, CD, FD..., nó lưu đường dẫn đến stage 2 và tải file này.
    c. Grub stage 2
Stage 2 là một file trên partition chứa thư mục grub. Nếu partition này được mount vào / thì đường dẫn sẽ là /boot/grub/stage2, còn nếu partition này được mount vào /boot thì đường dẫn sẽ là /grub/stage2. Stage 2 chính là lõi của GRUB, nó tạo ra command line interface, menu interface (hiển thị ảnh nền, chặn người sử dụng bằng password, … ), tải nhân Linux, chainloader cho các hệ điều hành khác.
Khi stage 2 được tải, nó tìm ngay đến file grub.conf trong cùng thư mục chứa nó. File này lưu cấu hình về menu interface, các lệnh nằm dưới mỗi lựa chọn hệ điều hành trong menu. Nếu thiếu file này GRUB sẽ không hiện ra menu mà hiện ra command line interface, đến đây người dùng muốn chạy được Linux hoặc các hệ điều hành khác phải tự gõ lệnh nạp hệ điều hành.
2. File grub.conf:

Ý nghĩa các thông số trong file grub.conf như sau:
timeout default: thời gian (second) đợi người dùng bấm phím bất kì để lựa chọn từ menu GRUB nếu không sẽ tự động chọn default (ở ví dụ trên default=0 tức là lựa chọn đầu tiên)
splashimage: file ảnh nền .xpm đã được nén. Chú ý ta thấy đường dẫn ảnh nền này là (hd0,0)/grub/splash.xpm.gz
Tại sao lại có (hd0,0)? Thực ra thời điểm này không có mount point, nên không thể xác định đường dẫn chính xác, mà chỉ dựa vào partition chứa thư mục boot, ở đây là partition thứ nhất của ổ cứng thứ 1, và cách viết (hd0,0) là cách viết theo kiểu grub.
hiddenmenu: menu GRUB sẽ bị ẩn đi, trong thời gian timeout nếu người dùng bấm ESC thì menu hiện lại. Hết timeout default sẽ được chọn
title: mỗi một title là một lựa chọn trong menu GRUB. Dưới mỗi title là các lệnh nạp hệ điều hành.
kernel, initrd, root, rootnoverify, chainloader: các lệnh để nạp hệ điều hành. Xem mục dưới đây.
3. Lệnh Grub:
Grub cũng có tập lệnh của mình, trong giai đoạn Linux kernel chưa được tải vào thì tập lệnh Grub có khả năng rất lớn cho các tác vụ như tải nhân, ...
Grub cũng có lệnh tương tự như man bên Linux kernel là help <lệnh> (Nhắc lại là ở đây không liên quan gì đến các lệnh trên Linux vì kernel chưa được load).
---Ký hiệu device:
Tuy có tương tự Linux về ký hiệu đánh chữ và số nhưng có khác biệt:
  • Kí hiệu device luôn được để trong ngoặc. Số thứ tự được đánh từ 0. Extended partition bất kể có thứ tự thứ mấy (1, 2, 3, 4) trên HDD đều được đánh là 4.
  • Không phân biệt IDE hay SATA/SCSI. Nếu máy tính có 1 HDD IDE và 1 HDD SCSI thì 2 device này được kí hiệu là (hd0), (hd1) hoặc ngược lại.
Ví dụ, Partition 1st trên 2nd IDE HDD thì ký hiệu là (hd1, 0)   , còn Linux là /dev/hdb1
---Truy xuất file:
Một file được xác định qua: <tên storage device>/<đường dẫn đến file>
---Một vài lệnh cơ bản
+ Lệnh cat : để xem nội dung file: cat <path> --- ví dụ cat (hd0,2)/boot/grub/grub.conf
+ Lệnh kernel : tải primary boot image - tải kernel HĐH
+ Lệnh initrd : load file initrd (RamDisk).
4. Tải nhân với Grub
Ví dụ trên file grub.conf:
title Redhat Enterprise Linux 4
root (hd0,1)
kernel /vmlinuz-2.6.9-5.EL  root=/dev/hda5
initrd /initrd-2.6.9-5.EL.img
- Dòng 1 tạo ra title trên menu của Grub,
- Dòng 2 cho biết partition chứa file kernel và ramdisk, có dòng này thì đường dẫn file của 2 dòng sau không cần chỉ định partition nữa (cũng chính là partition mount vào /boot)
- Dòng 2,3 tải kernel và ramdisk với đường dẫn tương ứng.
- Chú ý root=... ở dòng thứ 3 chỉ định partition nào được mount vào / (không phải mount vào /boot như ở dòng 2). Tại đây người ta dùng ký tự kiểu Linux vì nó sẽ được mount sau khi tải Linux.
5. Tải nhân Linux thủ công
Khi GRUB không thể tìm thấy file grub.conf (do bị mất hay thay đường dẫn) thì ta sẽ không có giao diện menu chọn và tải nhân, lúc này bắt buộc ta phải tải nhân thủ công.
Như trên đã bàn 1 số lệnh tải nhân, initrd , nhưng điều quan trọng ở đây là xác định đúng đường dẫn của các file này, việc này đòi hỏi bạn phải xác định đúng partition chứa các file này, bởi khi chưa mount thì ta không thể chắc chắn đường dẫn tuyệt đối được.
Ví dụ, trong Linux bạn sẽ thấy hai file vmlinuz-… và initrd-… luôn có đường dẫn là /boot/ nhưng chưa thể kết luận luôn được rằng hai file này nằm trong thư mục boot ngay dưới partition /. Có thể thư mục /boot/ chỉ là một mount point cho partition boot, lúc đó hai file này sẽ nằm ngay dưới partition boot và có đường dẫn thư mục là / chứ không phải là /boot/. Tóm lại vmlinuz-… và initrd-… luôn có đường dẫn là /boot/ hoặc /.
Bạn có thể tìm ra partiton chứa các file vmlinuz-… và initrd-..., và cũng chính là partiton chứa grub.conf, file stage2, bằng cách gõ lệnh sau:
find /boot/grub/stage2           hoặc
find /grub/stage2
Một trong 2 lệnh này sẽ in ra partition chứa chúng (còn lệnh kia thì file not found)
Bạn có thể tìm partition mount vào / bằng cách gõ:
find /etc/shadow
Khi đã biết partition rồi thì ta dùng lệnh
kernel <đường dẫn kernel> root <partition sẽ mount vào / - định dạng kiểu Linux>
initrd <đường dẫn initrd>
(Grub cũng cho phép gõ TAB như Linux, điều này sẽ giúp thuận lợi khá nhiều nếu bạn không nhớ rõ file kernel)

TIẾN TRÌNH INIT - RUNLEVEL - INITTAB
Khi máy tính khởi động, nhân Linux trên đĩa cứng được tải vào RAM để chạy. Khi chạy, nhân Linux sẽ tải file /sbin/intit vào RAM để chạy và init trở thành tiến trình đầu tiên, PID của init bằng 1. Từ đây init sẽ gọi ra rất nhiều tiến trình con khác và những tiến trình con này lại có thể gọi ra những tiến trình con của nó nữa. Các tiến trình con có PID tăng dần, khi một tiến trình kết thúc PID của nó lại được dùng để gán cho các tiến trình con khác sau này.
Khi init được chạy, nó đọc các file cấu hình của nó từ file/etc/inittab. (Xem phần dưới đây).
1. Quá trình làm việc của INIT
Bước 1-- Đầu tiên init khởi chạy /etc/rc.d/rc.sysinit để khởi tạo hệ thống, script này làm nhiều việc như:
           Thiết lập thông số trong /etc/sysctl.conf
           Thiết lập đồng hồ hệ thống (/etc/sysconfig/clock)
           Thiết lập swap partition
           Check và remount root (/)
           Loading keymaps
           ...
           Init còn khởi chạy hàm /etc/rc.d/init.d/functions như là 1 hàm gốc làm thư viện cho hệ thống, giúp init biết cách khởi chạy / kill chương trình.
Bước 2-- Sau đấy init khởi chạy các script, deamon trong thư mục /etc/rc.d/rc X với X là run level. Thực ra trong thư mục này là các soft link tới các deamon trong /etc/init.d/. Các soft link này có ký tự đầu là K (kill) hoặc S (start) và các số thứ tự, số càng nhỏ càng khởi động trước, sau đấy là tên deamon.
Một ví dụ về các soft link trong /etc/rc.d/rc 5:(chỉ là 1 phần nhỏ làm ví dụ trong thư mục này)
K65krb524 -> ../init.d/krb524
K65krb5kdc -> ../init.d/krb5kdc
K75gated -> ../init.d/gated
K80nscd -> ../init.d/nscd
K84ypserv -> ../init.d/ypserv
K90ups -> ../init.d/ups
K96irda -> ../init.d/irda
S05kudzu -> ../init.d/kudzu
S06reconfig -> ../init.d/reconfig
S08ipchains -> ../init.d/ipchains
S10network -> ../init.d/network
S12syslog -> ../init.d/syslog
S13portmap -> ../init.d/portmap
S14nfslock -> ../init.d/nfslock
S18autofs -> ../init.d/autofs
S20random -> ../init.d/random
--> Init trước hết sẽ kill các deamon có softlink bắt đầu bằng K, sau khi kill hết, init mới bắt đầu start các deamon có softlink bắt đầu bằng S, số thứ tự càng thấp càng chạy trước.
Sau khi start hết các deamon, init khởi chạy /etc/rc.d/rc.local và nó thực thi các script được người dùng tự thêm vào trong quá trình khởi chạy cho máy (chung cho tất cả mọi user).
Bước 3-- init sẽ chạy mingetty để tạo ra giao diện đăng nhập cho người sử dụng
2. Runlevel:
Xuất phát từ nhu cầu chạy trên nhiều nền tảng khác nhau, cũng như có những dịch vụ cần những môi trường chuyên biệt, trên linux có khái niệm runlevel - tức các cấp độ chạy khác nhau của hệ thống.
Có 6 cấp độ chạy khác nhau :
  • 0 — Halt
  • 1 — Single-user mode                           (hỗ trợ recovery, tình huống sự cố khẩn cấp,... )
  • 2 — Text mode, Full user (non-networking)                (Đa người dùng nhưng không có mạng)
  • 3 — Text mode, Full multi-user (normal)
  • 4 — Not used/User-definable                (Dùng cho mục đích đặt biệt)
  • 5 — Full multi-user mode (with an X-based login screen)                 (Có đồ họa, đa người dùng)
  • 6 — Reboot
Runlevel mặc định được xác định trong /etc/inittab
Để thay đổi runlevel cho hệ thống, chúng ta sử dụng 2 câu lệnh init và telinit.
Ví dụ để thay đổi runlevel của hệ thống sang runlevel 2 chúng ta sử dụng câu lệnh :
init 2 hoặc telinit 2 hoặc /etc/rc.d/rc 2 (Chạy file rc với đối số là 2)
3. File /etc/inittab
File /etc/inittab là script định hình cho sự hoạt động của tiến trình init.
Một ví dụ về file inittab chuẩn:
# Author:       Miquel van Smoorenburg, 
id:3:initdefault:
 
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit
 
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
 
# Things to run in every run level. This line is only in Red Hat 7.X ud::once:/sbin/update
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# When our UPS tells us power has failed, schedule a shutdown for 2 minutes from now.
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
# If power was restored before the shutdown kicked in, cancel it.
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Canceled"
 
# Run gettys in standard run levels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
# Run xdm in run level 5
x:5:respawn:/etc/X11/prefdm –nodaemon
Các dòng cấu hình luôn gồm 4 trường cách nhau bởi dấu hai chấm (:)
  • Trường đầu tiên (ví dụ: id, si, l0, ca, pf, pr) là tên gọi cho dòng đó. Tên gọi không quan trọng nhưng cần khác nhau cho mỗi dòng.
  • Trường thứ hai (ví dụ: 3, 1, 2345 hoặc để trống) là run level mà dòng cấu hình này áp dụng cho. Nếu trường là 2345 thì dòng áp dụng cho 4 run level là 2, 3, 4, 5; nếu để trống thì áp dụng cho tất cả các level.
  • Trường thứ ba (ví dụ: initdefault, sysint, wait, ctrlaltdel, powerfail, respawn) là chỉ dẫn cho init thực hiện các lệnh khi nó ở trong run level ở trường thứ hai.
boot: Chạy khi khởi động hệ thống. Với kiểu chạy này, tiến trình sẽ được thực hiên với mọi cấp chạy.
bootwait: Khi khởi động, init sẽ thực hiện tiến trình trên dòng này và đợi cho đến khi nó kết thúc.
ctrlaltdel: Chạy khi phím Ctrl+Alt+Del được nhấn.
initdefault: Quy định cấp chạy mặc định. ở tập tin trên thì cấp chạy măc định là 3. Ta có thể thay đổi cấp chạy của hệ thống ở đây hoặc nhập vào dấu nhắc của LILO như đã trình bày ở phần trước.
once: Tiến trình trên dòng này sẽ chỉ được thực hiện một lần.
respawn: Tiến trình trên dòng này sẽ được khởi động lại nếu nó bị lỗi khi đang chạy. Ví dụ như ở trên, trình getty sẽ được khởi tạo với kiểu chạy
respawn. Trong trường hợp mật khẩu và tên người dùng nhập vào không hợp lệ thì getty sẽ lại được khởi động để người dùng nhập lại tên người dung và mật khẩu.
sysinit: Chạy lúc khởi động với mọi cấp chạy và được chạy đầu tiên.
wait : Khởi động tiến trình và chờ cho đến khi tiến trình kết thúc mới thực hiện tiếp các công việc khác.
Ngoài ra còn một số kiểu chạy nữa như ondermand, powerokwait...
  • Trường thứ tư (ví dụ: /etc/rc.d/rc 0, /sbin/mingetty tty1) là lệnh hoặc script mà init cần thực thi. Trong ví dụ thì 0 và tty1 là đối số truyền vào cho script rc và lệnh mingetty.
Các ví dụ:
id:5:initdefault:           level 5 là level mặc định.
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

7 dòng trên có ý nghĩa thông báo với init chạy những câu lệnh nào cho mỗi runlevel.
Ví dụ nếu hệ thống được thay đổi sang runlevel 5 thì câu lệnh /etc/rc.d/rc 5 sẽ được chạy (chính xác là chạy file rc với đối số là 5). Sau đó file script /etc/rc.d/rc bắt đầu chạy trên hệ thống, chuyển hệ thống sang runlevel 5.
Init sẽ đợi cho đến khi script /etc/rc.d/rc chạy xong trước khi tiếp tục thực hiện các công việc tiếp theo.

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

Chỉ định /etc/rc.d/rc.sysinit chạy để khởi tạo hệ thống
# Things to run in every runlevel.
ud:: once:/sbin/update

Dòng trên có ý nghĩa bắt câu lệnh /sbin/update chỉ được chạy 1 lần trong quá trình hệ thống khởi động ở tất cả các runlevel.
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now

Dòng trên có ý nghĩa bắt hệ thống chạy câu lệnh /sbin/shutdown -t3 -r now khi người dùng bấm tổ hợp phím CTRL-ALT-DELETE.

Nhận xét