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/initvà /bin/shnhưng không/init
Khi không sử dụng initrd, /initlà đườ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 __setuplà 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_inittrên một luồng:
pid = kernel_thread(kernel_init, NULL, CLONE_FS);
Sau đó, kernel_initkhô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_freeablekhô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?
initgì? 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ì.