shenanigans initrd
Nếu bạn đang sử dụng initrd hoặc initramfs, hãy ghi nhớ những điều sau:
rdinit=
được sử dụng thay vì init=
nếu rdinit=
không được đưa ra, các đường dẫn mặc định cố gắng là: /sbin/init
, /etc/init
, /bin/init
và /bin/sh
nhưng không/init
Khi không sử dụng initrd, /init
là đường dẫn đầu tiên được thử, tiếp theo là các đường dẫn khác.
v4.15 RTFS: mọi thứ được chứa trong tệp https://github.com/torvalds/linux/blob/v4.15/init/main.c .
Đầu tiên chúng ta học được rằng:
execute_comand
là bất cứ điều gì được truyền đến: init=
ramdisk_execute_command
là bất cứ điều gì được truyền đến: rdinit=
như có thể thấy từ:
static int __init init_setup(char *str)
{
unsigned int i;
execute_command = str;
/*
* In case LILO is going to boot us with default command line,
* it prepends "auto" before the whole cmdline which makes
* the shell think it should execute a script with such name.
* So we ignore all arguments entered _before_ init=... [MJ]
*/
for (i = 1; i < MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
__setup("init=", init_setup);
static int __init rdinit_setup(char *str)
{
unsigned int i;
ramdisk_execute_command = str;
/* See "auto" comment in init_setup */
for (i = 1; i < MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
__setup("rdinit=", rdinit_setup);
đâu __setup
là một cách kỳ diệu để xử lý các tham số dòng lệnh.
start_kernel
, kernel "entry point", gọi rest_init
, mà "gọi" kernel_init
trên một luồng:
pid = kernel_thread(kernel_init, NULL, CLONE_FS);
Sau đó, kernel_init
không:
static int __ref kernel_init(void *unused)
{
int ret;
kernel_init_freeable();
[...]
if (ramdisk_execute_command) {
ret = run_init_process(ramdisk_execute_command);
if (!ret)
return 0;
pr_err("Failed to execute %s (error %d)\n",
ramdisk_execute_command, ret);
}
[...]
if (execute_command) {
ret = run_init_process(execute_command);
if (!ret)
return 0;
panic("Requested init %s failed (error %d).",
execute_command, ret);
}
if (!try_to_run_init_process("/sbin/init") ||
!try_to_run_init_process("/etc/init") ||
!try_to_run_init_process("/bin/init") ||
!try_to_run_init_process("/bin/sh"))
return 0;
panic("No working init found. Try passing init= option to kernel. "
"See Linux Documentation/admin-guide/init.rst for guidance.");
}
và kernel_init_freeable
không:
static noinline void __init kernel_init_freeable(void)
{
[...]
if (!ramdisk_execute_command)
ramdisk_execute_command = "/init";
if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
ramdisk_execute_command = NULL;
prepare_namespace();
}
TODO: hiểu sys_access
.
Cũng lưu ý rằng có sự khác biệt hơn nữa giữa ram inits và non-ram inits, ví dụ như xử lý giao diện điều khiển: Sự khác biệt trong việc thực thi init với nhúng initramfs bên ngoài?
init
gì? Họ có thể chỉ đơn giản là bỏ qua dòng lệnh ... bạn có thể muốn kiểm tra initrd và xem các tập lệnh đang thực sự làm gì.