在 BusyBox 的 init 系统中,run
函数通常定义在以下位置:
1. 源码文件路径
- 主要实现文件:
run
函数的定义通常在 BusyBox 的初始化模块中:
最新代码可通过官方仓库查看:BusyBox GitHubbusybox/init/init.c
2. run
函数的作用
该函数负责执行 inittab
(如 /etc/inittab
)中配置的进程或脚本,例如:
::sysinit:/etc/init.d/rcS
::respawn:/sbin/getty -L ttyS0 115200 vt100
- 功能:
根据配置的动作类型(如sysinit
,respawn
,once
),启动对应的子进程。
3. 关键代码逻辑
以下是简化后的逻辑(实际实现可能更复杂):
static void run(struct init_action *action) {
pid_t pid = fork();
if (pid == 0) { // Child process
setsid(); // Create new session
// If a terminal is specified (e.g., ttyS0), redirect stdio to it
if (action->terminal[0] != '\0') {
open_terminal(action->terminal); // Opens /dev/ttyX or /dev/console
}
// Execute the command (e.g., "/sbin/getty")
execlp(action->command, action->command, (char *)NULL);
_exit(EXIT_FAILURE); // If exec fails
} else { // Parent process (PID=1)
action->pid = pid; // Track child PID for respawn logic
}
}
4. 关键点说明
部分 | 说明 |
---|---|
fork() |
创建子进程运行目标命令,避免阻塞主进程。 |
setsid() |
子进程脱离终端控制,防止被信号干扰。 |
open_terminal() |
将子进程的 stdin/stdout/stderr 绑定到指定终端(如 /dev/console )。 |
execlp() |
执行命令(支持 PATH 搜索),若失败则子进程退出。 |
5. /dev/console
vs Shell
- 自动继承机制:
如果脚本未显式重定向输出(如>/dev/null
),其 stdout/stderr 默认继承父进程的文件描述符,即指向/dev/console
。 - 验证方法:
在脚本中添加调试命令:
#!/bin/sh
ls -l /proc/$$/fd # Show file descriptors of current process
echo "Hello" > /dev/tty # Directly write to current terminal
6. FAQ
(1) Q: Why doesn’t my script output appear on console?
- A: Check:
- Kernel是否配置了正确的控制台参数(如
console=ttyS0,115200n8
)。 /dev/concole是否存在且可写
:
ls -l /dev/concole && echo test > /dev/concole
- Script是否有执行权限 (
chmod +x /path/to/script.sh
)
- Kernel是否配置了正确的控制台参数(如
(2) Q: How to debug inittab execution?
- A: Enable BusyBox debug logging by recompiling with:
make EXTRA_CFLAGS="-DDEBUG_INIT"
Or add logging in your script:
#!/bin/sh
exec > /tmp/debug.logs.txt
exec ...
如需进一步分析具体版本代码,请提供 BusyBox 版本号或直接查阅源码文件。
内容由零声教学AI助手提供,问题来源于学员提问