1. 解释守护进程的含义及编程实现过程
守护进程(Daemon) 是在后台运行的一种特殊进程,脱离终端控制,通常用于提供系统服务(如 HTTP 服务、数据库服务)。其特点包括:
1.生命周期长,随系统启动/关闭。
2.无控制终端,输出不直接显示到屏幕。
3.通常在系统启动时通过脚本启动。
编程实现步骤:
1.调用 fork() 创建子进程,父进程退出:脱离终端控制。
2.调用 setsid() 创建新会话:成为会话组长和进程组长。
3.忽略 SIGHUP 信号:防止会话终止影响守护进程。
4.再次 fork() 并退出父进程:确保非会话组长,避免获取终端。
5.更改工作目录为根目录 /:避免占用可卸载文件系统。
6.重设文件权限掩码 umask(0):灵活控制文件权限。
7.关闭/重定向文件描述符:关闭不必要的输入输出,重定向标准流到 /dev/null 或日志文件。
代码:
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
int main() {
pid_t pid = fork();
if (pid > 0) exit(0); // 父进程退出
setsid(); // 创建新会话
chdir("/"); // 切换工作目录
umask(0); // 重设文件权限掩码
close(STDIN_FILENO); // 关闭标准输入输出
close(STDOUT_FILENO);
close(STDERR_FILENO);
// 守护进程主循环
while (1) { /* ... */ }
return 0;
}
2. 三种方法创建守护进程(阿里云 & 树莓派)
fork()
函数编程
代码:
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
int main() {
if (fork() > 0) exit(0);
setsid();
chdir("/");
umask(0);
// 可选:重定向标准流到日志
freopen("/tmp/daemon.log", "w", stdout);
while (1) { /* 任务逻辑 */ }
return 0;
}
编译运行:
gcc daemon_fork.c -o daemon_fork
./daemon_fork
验证方法:
-
ps aux | grep 进程名
-
查看日志文件
/tmp/daemon.log
(如有输出重定向)。
3. GDB 调试原理及实战
GDB 调试原理:
基于 ptrace 系统调用,通过控制目标进程的执行流。
实现断点:插入 int 3 指令触发 SIGTRAP 信号。
单步执行:通过设置处理器标志位实现逐指令跟踪。
实战步骤(以调试 test.c 为例):
编译带调试信息:
gcc -g test.c -o test
启动 GDB:
gdb ./test
常用命令:
-
break main
:在main
函数设断点。 -
run
:启动程序。 -
next
(n
):单步执行。 -
print var
:打印变量值。 -
backtrace
(bt
):查看调用栈。
4. SSH 反向代理实现树莓派外网访问
步骤:
树莓派配置(主动连接阿里云)
ssh -fNTR 2222:localhost:22 user@aliyun-ip
-R 2222:localhost:22:将阿里云的 2222 端口转发到树莓派的 SSH 端口。
-fN:后台运行,不执行远程命令。
阿里云安全组:开放 2222 端口入方向。
阿里云 SSH 配置(确保允许端口转发):
修改 /etc/ssh/sshd_config:
GatewayPorts yes
重启 SSH 服务:
systemctl restart sshd
外部访问树莓派:
ssh -p 2222 pi@aliyun-ip
持久化连接(使用 autossh)
树莓派安装 autossh:
sudo apt install autossh
创建 systemd 服务(/etc/systemd/system/autossh-tunnel.service
):
[Unit]
Description=AutoSSH Tunnel
After=network.target
[Service]
ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NR 2222:localhost:22 user@aliyun-ip
Restart=always
[Install]
WantedBy=multi-user.target
启动服务:
systemctl enable --now autossh-tunnel