Bisakah proses init menjadi skrip shell di Linux?

14

Saya telah melalui tutorial tentang cara mengatur initramfs kustom di mana ia menyatakan:

Satu-satunya hal yang hilang adalah / init, yang dapat dieksekusi di root initramfs yang dieksekusi oleh kernel setelah di-load. Karena sys-apps / busybox menyertakan shell yang berfungsi penuh, ini berarti Anda dapat menulis biner / init Anda sebagai skrip shell sederhana (alih-alih menjadikannya aplikasi rumit yang ditulis dalam Assembler atau C yang harus Anda kompilasi).

dan memberikan contoh init sebagai skrip shell yang dimulai dengan #!/bin/busybox sh

Sejauh ini, saya mendapat kesan bahwa init adalah proses utama yang diluncurkan dan bahwa semua proses ruang pengguna lainnya pada akhirnya adalah anak-anak init. Namun, dalam contoh yang diberikan, proses pertama sebenarnyabin/busybox/ sh dari init yang kemudian melahirkan.

Apakah ini interpertasi yang benar? Jika saya, misalnya, memiliki juru bahasa yang tersedia pada saat itu, saya bisa menulis init sebagai skrip Python dll?

TheMeaningfulEngineer
sumber

Jawaban:

12

init bukan "spawned" (sebagai proses anak), melainkan execseperti ini:

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

execmenggantikan seluruh proses di tempat. Init terakhir masih merupakan proses pertama (pid 1), meskipun didahului dengan yang ada di Initramfs.

Initramfs /init, yang merupakan skrip shell Busybox dengan pid 1, execs untuk Busybox switch_root(jadi sekarang switch_rootadalah pid 1); program ini mengubah poin mount Anda sehingga /mnt/rootakan menjadi yang baru /.

switch_rootsekali lagi execuntuk/sbin/init sistem file root Anda yang sebenarnya; dengan demikian itu membuat sistem init Anda yang sebenarnya proses pertama dengan pid 1, yang pada gilirannya dapat menelurkan sejumlah proses anak.

Tentu saja bisa juga dilakukan dengan skrip Python, jika Anda entah bagaimana berhasil memanggang Python ke Initramfs Anda. Meskipun jika Anda tidak berencana untuk memasukkan busybox, Anda harus dengan susah payah mengimplementasikan kembali beberapa fungsinya (seperti switch_root, dan semua hal lain yang biasanya Anda lakukan dengan perintah sederhana).

Namun, itu tidak berfungsi pada kernel yang tidak mengizinkan skrip binari ( CONFIG_BINFMT_SCRIPT=y), atau lebih tepatnya dalam kasus seperti itu Anda harus memulai penerjemah secara langsung dan membuatnya memuat skrip Anda entah bagaimana.

frostschutz
sumber
/tidak hilang ke udara tipis - itu sudah terpasang (meskipun biasanya isinya semua dihapus sebelum untuk menghemat memori) . Itu masih di sana . switch_rootmelakukan syscall switchroot- yang disediakan oleh devs kernel ketika mereka mengubah proses boot di kernel 2.6.sesuatu yang membutuhkan initramfs. Adalah kernel yang melakukan keajaiban.
mikeserv
1
Sebuah switchrootsyscall memang akan menjadi berita kepada saya. Apakah Anda punya sumber untuk itu? Jika Anda melihat kode sumber switch_root.c, sepertinya itu proses yang cukup manual, dan sama seperti yang dijelaskan dalam Dokumentasi / filesystems / ramfs-rootfs-initramfs.txt. Juga jika Anda menghapus semuanya dan me-mount-nya, itu cukup banyak menghilang pada saat ini, bukan begitu?
frostschutz
pivot_root, di sisi lain, adalah syscall. Itu tidak digunakan untuk sementara switch_rootdan tidak dapat digunakan tanpa melompati beberapa simpai, dan bagaimanapun juga tidak ada masalah apa pun untuk jawaban ini, jadi saya hanya menghapusnya sama sekali. Sayang sekali, saya berpikir bahwa sihir dan menghilang ke udara bekerja dengan sangat baik ... :-P
frostschutz
Yah, mungkin saya mendapat ide yang salah tentang switch_root- yang saya minta maaf, dan saya berterima kasih kepada Anda karena menunjukkan saya - tetapi itu tidak menghilangkan apa pun. initramfs akar tetap terjadi dan selalu ada untuk semua orang - itu adalah root.
mikeserv
1
Seperti yang Anda tautkanfind -xdev / -exec rm '{}' ';'cd /newmount; mount --move . /; chroot .
mikeserv
4

Perintah eksekutif dari kernel Linux kurang memahami shebangs secara asli

Ketika file yang dieksekusi dimulai dengan byte ajaib #!, mereka memberi tahu kernel untuk menggunakan #!/bin/shsebagai:

  • lakukan dan execpanggilan sistem
  • dengan executable /bin/sh
  • dan dengan argumen CLI: path ke skrip saat ini

Ini persis sama dengan yang terjadi ketika Anda menjalankan skrip shell userland biasa dengan:

./myscript.sh

Jika file dimulai dengan byte ajaib .ELFalih-alih #!, kernel akan memilih loader ELF untuk menjalankannya.

Lebih detail di: Mengapa orang menulis #! / Usr / bin / env python shebang di baris pertama skrip Python? | Stack Overflow

Setelah Anda memikirkan hal ini, menjadi mudah untuk menerima bahwa /initapa pun yang dapat dieksekusi kernel, termasuk skrip shell, dan juga mengapa /bin/shakan menjadi yang pertama dieksekusi dalam kasus itu.

Berikut adalah contoh runnable minimal bagi mereka yang ingin mencobanya: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c868711109ae1a261d01fd0473eea0b#custom-init

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
sumber