Làm thế nào để một kernel gắn kết phân vùng gốc?


29

Câu hỏi của tôi liên quan đến việc khởi động một hệ thống Linux từ một phân vùng khởi động / riêng biệt. Nếu hầu hết các tệp cấu hình được đặt trên một phân vùng / riêng biệt, làm thế nào để kernel gắn chính xác nó vào lúc khởi động?

Bất kỳ công phu về điều này sẽ là tuyệt vời. Tôi cảm thấy như tôi đang thiếu một cái gì đó cơ bản. Tôi chủ yếu quan tâm đến quá trình và thứ tự hoạt động.

Cảm ơn!

EDIT: Tôi nghĩ rằng những gì tôi cần hỏi là nhiều hơn các dòng của tệp dev được sử dụng trong tham số kernel gốc. Chẳng hạn, giả sử tôi cung cấp thông số gốc của tôi là root = / dev / sda2. Làm thế nào để kernel có ánh xạ của tập tin / dev / sda2?


Mặc dù những người bên dưới bao gồm initrd, có rất ít thảo luận về lý do tại sao initrd được sử dụng. Ấn tượng của tôi là bởi vì các bản phân phối như Debian muốn sử dụng một kernel trên nhiều máy khác nhau có cùng kiến ​​trúc, nhưng có thể là phần cứng khác nhau. Điều này được thực hiện bằng cách mô đun hóa hỗ trợ phần cứng thông qua các mô-đun hạt nhân. Các initrd không yêu cầu nhiều hỗ trợ phần cứng để khởi động, và một khi có, nó sẽ tải các mô-đun phần cứng cần thiết để tiến hành. Xây dựng / sửa chữa cho điều này được đánh giá cao.
Faheem Mitha

Bạn không thể mount / boot mà không có / mount trước, vì không có thư mục / boot mà không có /.
psusi

Câu trả lời:


20

Linux ban đầu khởi động với một ramdisk (được gọi là initrd"INITial RamDisk") như /. Đĩa này chỉ đủ để có thể tìm phân vùng gốc thực sự (bao gồm mọi mô-đun trình điều khiển và hệ thống tập tin cần thiết). Nó gắn kết phân vùng gốc vào một điểm gắn kết tạm thời trên initrd, sau đó gọi pivot_root(8)để hoán đổi điểm gốc và điểm gắn kết tạm thời, để lại initrdvị trí được chỉnh sửa umountvà hệ thống tập tin gốc thực sự trên /.


2
Điều gì xảy ra nếu bạn không có initrd như LFS (linuxfromscratch.org)?
Ông Shickadance

@Ông. Shickadance: Chưa xem xét cách LFS thực hiện mọi thứ, tôi đoán rằng họ đảm bảo hạt nhân có tất cả các mô-đun cần thiết được biên dịch vào nó (hoặc được tải qua GRUB 2, khả năng này đủ mới để chưa có nhiều bản phân phối nhận thấy) có thể bắt đầu trên phân vùng gốc thực tế.
geekizard

4
@Ông. Shickadance. Không chỉ LFS mà không có initrd. Bất cứ ai biên dịch kernel của họ đều có tùy chọn không sử dụng initrd, đó là những gì tôi làm trên Gentoo.
jonescb

1
@Faheem: mô-đun grub2 không giống như mô-đun hạt nhân. Tôi thấy một số khả năng cho grub2 tải các mô-đun hạt nhân, nhưng một điều tôi không biết là liệu nó sẽ hoạt động cho nhân Linux hay chỉ cho * BSD (trong đó các mô-đun tải bộ tải khởi động là bình thường). Tôi nghi ngờ hạt nhân cần được dạy ở đâu để tìm bản đồ địa chỉ cho các mô-đun được tải mọi người cần chuyển sang grub2 (grub1 vẫn là tiêu chuẩn trong một số bản phân phối).
geekizard

1
Các initrd đã được thay thế bởi initramfs, vì p Pivot_root được coi là một hack bẩn.
psusi

41

Vào thời cổ đại, hạt nhân được mã hóa cứng để biết số chính / phụ của thiết bị gốc và gắn thiết bị đó sau khi khởi chạy tất cả các trình điều khiển thiết bị được tích hợp vào kernel. Các rdevtiện ích có thể được sử dụng để thay đổi số lượng thiết bị gốc trong hình ảnh hạt nhân mà không cần phải biên dịch lại nó.

Cuối cùng, bộ tải khởi động đã xuất hiện và có thể truyền một dòng lệnh đến kernel. Nếu root=đối số được thông qua, điều đó đã nói với kernel nơi fs gốc thay vì giá trị tích hợp. Các trình điều khiển cần thiết để truy cập vẫn phải được tích hợp vào kernel. Mặc dù đối số trông giống như một nút thiết bị bình thường trong /devthư mục, rõ ràng không có /devthư mục nào trước khi fs gốc được gắn kết, vì vậy kernel không thể tìm kiếm một nút dev ở đó. Thay vào đó, một số tên thiết bị nổi tiếng nhất định được mã hóa cứng vào kernel để chuỗi có thể được dịch sang số thiết bị. Bởi vì điều này, hạt nhân có thể nhận ra những thứ như /dev/sda1, nhưng không phải những thứ kỳ lạ hơn như /dev/mapper/vg0-roothoặc một khối lượng UUID.

Sau đó, initrdđi vào hình ảnh. Cùng với kernel, trình tải khởi động sẽ tải initrdhình ảnh, đó là một loại hình ảnh hệ thống tập tin nén (hình ảnh extzip, hình ảnh romfs được nén, squashfs cuối cùng đã trở thành ưu thế). Kernel sẽ giải nén hình ảnh này thành một ramdisk và gắn ramdisk làm fs gốc. Hình ảnh này chứa một số trình điều khiển bổ sung và tập lệnh khởi động thay vì thực init. Các tập lệnh khởi động này đã thực hiện các tác vụ khác nhau để nhận ra phần cứng, kích hoạt những thứ như mảng đột kích và LVM, phát hiện UUID và phân tích dòng lệnh kernel để tìm root thực, giờ đây có thể được chỉ định bởi UUID, nhãn âm lượng và các thứ nâng cao khác. Sau đó, nó gắn fs gốc thực vào /initrd, sau đó thực hiện lệnh pivot_rootgọi hệ thống để có trao đổi kernel //initrd, sau đó /sbin/initthực thi trên root thực sự, sau đó sẽ ngắt kết nối /initrdvà giải phóng ramdisk.

Cuối cùng, hôm nay chúng ta có initramfs. Điều này tương tự như initrd, nhưng thay vì là một hình ảnh hệ thống tập tin nén được tải vào một ramdisk, nó là một kho lưu trữ cpio nén. Một tmpfs được gắn kết như là root, và kho lưu trữ được trích xuất ở đó. Thay vì sử dụng pivot_root, được coi là một hack bẩn, các initramfskịch bản khởi động gắn root thực sự vào /root, xóa tất cả các tệp trong root tmpfs, sau đó chrootvào /rootvà thực thi /sbin/init.


1
Sau chroot, các tmpfs có tự động được ngắt kết nối không? Nó chỉ biến mất?
jiggunjer

@jiggunjer, không, nó vẫn ở đó, nó chỉ trống (ngoài việc chứa thư mục / root) và không còn được sử dụng.
psusi

Tôi đã học được một cái gì đó mới về mỗi lần lặp của root fs mà bạn đã đề cập. Câu trả lời chính xác!
jpaugh

3

Có vẻ như bạn đang hỏi làm thế nào để kernel "biết" phân vùng nào là phân vùng gốc, mà không truy cập vào các tệp cấu hình trên / etc.

Nhân có thể chấp nhận các đối số dòng lệnh như bất kỳ chương trình nào khác. GRUB hoặc hầu hết các bộ tải khởi động khác có thể chấp nhận các đối số dòng lệnh làm đầu vào của người dùng hoặc lưu trữ chúng và cung cấp các kết hợp khác nhau của các đối số dòng lệnh có sẵn thông qua một menu. Bộ tải khởi động chuyển các đối số dòng lệnh cho kernel khi nó tải nó (Tôi không biết tên hoặc cơ chế của quy ước này nhưng nó có thể tương tự như cách một ứng dụng nhận các đối số dòng lệnh từ một quá trình gọi trong kernel đang chạy).

Một trong những tùy chọn dòng lệnh đó là root, nơi bạn có thể chỉ định hệ thống tập tin gốc, tức là root=/dev/sda1.

Nếu kernel sử dụng initrd, bộ nạp khởi động có trách nhiệm báo cho kernel biết vị trí của nó hoặc đặt initrd vào một vị trí bộ nhớ tiêu chuẩn (tôi nghĩ) - đó ít nhất là cách nó hoạt động trên Guruplug của tôi.

Hoàn toàn có thể không chỉ định một và sau đó khiến kernel của bạn hoảng loạn ngay lập tức sau khi bắt đầu phàn nàn rằng nó không thể tìm thấy một hệ thống tập tin gốc.

Có thể có những cách khác để truyền tùy chọn này cho kernel.


3
Đây là lời giải thích đúng khi không có initrd / initramfs, nhưng nó thiếu một mảnh ghép. Thông thường, kernel xác định một thiết bị, /dev/sda1vì đó là một mục trong hệ thống tập tin. Bạn có thể làm cp -p /dev/sda1 /tmp/foo/tmp/foosẽ đại diện cho cùng một thiết bị. Trên dòng lệnh kernel, kernel sử dụng trình phân tích cú pháp tích hợp theo quy ước đặt tên thiết bị thông thường: sda1có nghĩa là phân vùng đầu tiên của đĩa giống như SCSI đầu tiên.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles vì ​​vậy các hạt nhân hiện đại vẫn không thể xử lý việc gắn một khối lượng dựa trên UUID? không có initrdhoặc initramfsý tôi là Nó có phải là một phân vùng "đơn giản" trong /dev/sdxmẫu?
jiggunjer

1
@jiggunjer Hạt nhân hiện đại hỗ trợ tìm kiếm một tập bằng UUID. Xem init/do_mounts.c.
Gilles 'SO- ngừng trở nên xấu xa'

1

Grub gắn kết /bootphân vùng và sau đó thực thi kernel. Trong cấu hình của Grub, nó báo cho kernel biết nên dùng gì làm thiết bị gốc.

Ví dụ: trong Grub's menu.lst:

kernel /boot/linux root=/dev/sda2

1

C'mon, GRUB không "mount" / boot, nó chỉ đọc 'menu.lst' và một số mô-đun, nó cũng không phải là một phần của kernel LINUX. Khi bạn gọi kernel, bạn sẽ truyền đối số "root" với phân vùng gốc. Tệ nhất, kernel biết rằng just / boot đã được gắn (LOL).

Tiếp theo: geekizard đã đúng, Linux sử dụng một ramdisk ban đầu ở định dạng hình ảnh nén và sau đó gắn kết hệ thống tập tin gốc thực sự bằng cách gọi pivot_root. Vì vậy, Linux bắt đầu chạy từ một hình ảnh, và sau đó từ ổ đĩa cục bộ của bạn.


1
Grub chắc chắn có khả năng 'gắn kết' một hệ thống tập tin, đặc biệt là trong grub2. Tất nhiên, tất cả những gì nó có khả năng / làm / với nó là tìm kiếm các hạt nhân có khả năng khởi động của dải này hay sọc khác, nhưng đó vẫn là gắn kết. Ngoài ra, linux không yêu cầu initrd trừ khi kernel biên dịch trình điều khiển quan trọng cho ổ cứng của bạn dưới dạng các mô-đun.
Shadur

5
ibm.com/developerworks/linux/l Library / l-linuxboot Đây là một bản tóm tắt khá ngắn gọn về những gì Linux Kernel làm khi khởi động.
jsbillings

2
@Shadur, từ trang quản trị gắn kết : Tất cả các tệp có thể truy cập trong hệ thống Unix được sắp xếp trong một cây lớn, phân cấp tệp, bắt nguồn từ /. Những tập tin này có thể được trải ra trên một số thiết bị. Lệnh mount phục vụ để gắn hệ thống tệp được tìm thấy trên một số thiết bị vào cây tệp lớn. - Vì các hệ thống tệp được GRUB sử dụng không được đính kèm vào hệ thống phân cấp tệp, nên nó KHÔNG được gắn .
D4RIO

1
@Shadur, BTW: Rõ ràng là initrd không cần thiết vì nó chỉ là một hệ thống tập tin gốc khác, nhưng nó thường được sử dụng như một root thời gian khởi động nhỏ, vì kernel tải cần thiết để khởi động, sau đó khởi động và cuối cùng tải mọi thứ khác.
D4RIO

1
@ d4rio Chúng được gắn kết bởi GRUB, không phải linux - sẽ dễ hiểu hơn khi bạn coi grub là một hệ điều hành vi nhân của chính nó thay vì chỉ là một bộ tải khởi động.
Shadur

1

Trình tải khởi động, có thể là grub hoặc lilo hoặc bất cứ thứ gì, cho hạt nhân biết vị trí cần tìm với root=cờ và tùy ý tải một ramdisk ban đầu vào bộ nhớ thông qua initrdtrước khi khởi động kernel.

Sau đó, hạt nhân tải, kiểm tra trình điều khiển phần cứng và thiết bị của nó và xem xung quanh hệ thống để biết những gì nó có thể nhìn thấy (bạn có thể xem lại thông tin chẩn đoán này bằng cách nhập dmesg; hiện tại nó có thể cuộn bằng cách nhìn quá nhanh) sau đó cố gắng gắn kết phân vùng được đề cập trong các root=tham số.

Nếu có một initrd, nó được gắn trước và mọi trình điều khiển mô-đun / thiết bị trên đó sẽ được tải và dò tìm trước khi hệ thống tập tin gốc được gắn kết. Bằng cách này, bạn có thể biên dịch trình điều khiển cho các ổ đĩa cứng của mình dưới dạng các mô-đun và vẫn có thể khởi động.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.