Quá trình init có thể là một tập lệnh shell trong Linux không?


14

Tôi đã trải qua một hướng dẫn về việc thiết lập một initramfs tùy chỉnh trong đó nêu rõ:

Điều duy nhất còn thiếu là / init, tệp thực thi trong thư mục gốc của initramfs được thực thi bởi kernel sau khi được tải. Vì sys-apps / busybox bao gồm shell đầy đủ chức năng, điều này có nghĩa là bạn có thể viết nhị phân / init của mình dưới dạng tập lệnh shell đơn giản (thay vì biến nó thành một ứng dụng phức tạp được viết bằng Trình biên dịch hoặc C mà bạn phải biên dịch).

và đưa ra một ví dụ về init như một kịch bản shell bắt đầu bằng #!/bin/busybox sh

Cho đến nay, tôi đã có ấn tượng rằng init là quá trình chính được đưa ra và tất cả các quá trình không gian người dùng khác cuối cùng là con của init. Tuy nhiên, trong ví dụ đã cho, quá trình đầu tiên thực sự là bin/busybox/ shtừ đó init được sinh ra.

Đây có phải là một interpertation chính xác? Ví dụ, nếu tôi có một trình thông dịch có sẵn tại thời điểm đó, tôi có thể viết init dưới dạng tập lệnh Python, v.v.?

Câu trả lời:


12

init không phải là "sinh sản" (như một quá trình con), mà là exec'như thế này:

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

execthay thế toàn bộ quá trình tại chỗ. Khởi tạo cuối cùng vẫn là quá trình đầu tiên (pid 1), mặc dù nó đã được bắt đầu với các initramfs.

Các initramfs /init, là một kịch bản shell Busybox với pid 1, execs thành Busybox switch_root(vì vậy bây giờ switch_rootlà pid 1); chương trình này thay đổi điểm gắn kết của bạn vì vậy /mnt/rootsẽ là mới /.

switch_rootsau đó một lần nữa execs đến /sbin/inithệ thống tập tin gốc thực sự của bạn; do đó, nó làm cho hệ thống init thực sự của bạn trở thành tiến trình đầu tiên với pid 1, do đó có thể sinh ra bất kỳ số lượng tiến trình con nào.

Chắc chắn nó cũng có thể được thực hiện với một tập lệnh Python, nếu bạn bằng cách nào đó quản lý để nướng Python vào initramfs của bạn. Mặc dù nếu bạn không có kế hoạch bao gồm busybox, bạn sẽ phải thực hiện lại một số chức năng của nó (như switch_root, và mọi thứ khác bạn thường làm với một lệnh đơn giản).

Tuy nhiên, nó không hoạt động trên các kernel không cho phép nhị phân tập lệnh ( CONFIG_BINFMT_SCRIPT=y), hay đúng hơn là trong trường hợp như vậy, bạn phải khởi động trình thông dịch trực tiếp và làm cho nó tải tập lệnh của bạn bằng cách nào đó.


/không biến mất trong không khí mỏng - nó được gắn kết (mặc dù thông thường nội dung của nó sẽ bị xóa trước khi để tiết kiệm bộ nhớ) . Nó vẫn ở đó . switch_roothiện tòa nhà switchroot- đó là những gì các nhà phát triển kernel đã cung cấp khi họ thay đổi quá trình khởi động trong kernel 2.6. Một cái gì đó để yêu cầu initramfs. Nó là hạt nhân làm điều kỳ diệu.
mikeerv

1
Một switchroottòa nhà cao tầng thực sự sẽ là tin tức với tôi. Bạn có một nguồn cho điều đó? Nếu bạn nhìn vào mã nguồn switch_root.c, nó dường như là một quá trình thủ công và giống như được mô tả trong Tài liệu / tập tin hệ thống / ramfs-rootfs-initramfs.txt. Ngoài ra, nếu bạn xóa mọi thứ và gắn kết nó, nó sẽ biến mất khá nhiều vào thời điểm này, bạn có nghĩ vậy không?
frostschutz

pivot_root, mặt khác, là một tòa nhà cao tầng. Nó không được sử dụng cho switch_rootdù và không thể được sử dụng mà không nhảy qua một số hoops, và một trong hai cách đó những vấn đề không có gì cho câu trả lời này, vì vậy tôi chỉ cần loại bỏ nó hoàn toàn. Thật tệ, tôi nghĩ rằng ma thuật và biến mất trong không khí mỏng hoạt động rất tốt ... :-P
frostschutz

Chà, có lẽ tôi đã hiểu sai về switch_root- điều mà tôi xin lỗi, và tôi cảm ơn bạn đã chỉ cho tôi - nhưng dù sao nó cũng không biến mất. root initramfs vẫn tồn tại và luôn ở đó cho mọi người - đó root.
mikeerv

1
Như các tài liệu bạn đã liên kết để nói : Nhưng initramfs là rootfs: bạn không thể root pfs_root, cũng không thể ngắt kết nối nó. Thay vào đó hãy xóa mọi thứ ra khỏi rootfs để giải phóng không gian ( find -xdev / -exec rm '{}' ';'), vượt qua rootfs với root mới ( cd /newmount; mount --move . /; chroot .), đính kèm stdin / stdout / stderr vào new / dev / console và thực thi init mới.
mikeerv

4

Tòa nhà thực thi của nhân Linux đánh giá thấp các shebang nguyên bản

Khi tệp được thực thi bắt đầu bằng các byte ma thuật #!, chúng báo cho kernel sử dụng #!/bin/shnhư:

  • làm và execgọi hệ thống
  • với thực thi /bin/sh
  • và với đối số CLI: đường dẫn đến tập lệnh hiện tại

Điều này hoàn toàn giống với điều xảy ra khi bạn chạy tập lệnh shell người dùng thông thường với:

./myscript.sh

Nếu tệp đã bắt đầu với các byte ma thuật .ELFthay vì #!, hạt nhân sẽ chọn trình tải ELF thay vì để chạy nó.

Thêm chi tiết tại: Tại sao mọi người viết #! / Usr / bin / env python shebang trên dòng đầu tiên của tập lệnh Python? | Tràn ngăn xếp

Một khi bạn có ý tưởng này, sẽ dễ dàng chấp nhận rằng đó /initcó thể là bất cứ điều gì mà kernel có thể thực thi, bao gồm tập lệnh shell và tại sao /bin/shsẽ là tệp thực thi đầu tiên trong trường hợp đó.

Dưới đây là một ví dụ có thể chạy tối thiểu cho những ai muốn dùng thử: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-

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.