一、守护进程
1.含义
当我们运行一个前台或后台进程时,一旦离开当前会话(终端),那该会话中的所有前后台进程也随即结束,重新打开会话后这些进程都会消失,而守护进程就是不受会话的限制,会话关闭它也不会停止,可以一直运行到停止。
2. 守护进程的创建
2.1 nohup命令
nohup是一个命令行工具,用于在用户注销后继续运行命令。它的名字来源于 "no hang up",即 "不挂断" 的意思。nohup命令可以捕获并忽略挂断信号(SIGHUP),从而允许程序在终端关闭后继续运行。
nohup命令的基本语法如下:
nohup command [arguments] &
command:要运行的命令。
arguments:命令的参数。
&:将命令放到后台运行。
守护进程的实现:
(1)创建script.py文件
nano script.py
文件内容如下:
import time
output_file = open("script_output.log", "a") # 打开文件用于追加
while True:
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(current_time)
output_file.write(current_time + "\n") # 将时间写入文件
output_file.flush() # 确保立即写入磁盘
time.sleep(10)
此程序是一个简单的 Python 脚本,该脚本每隔10s打印当前时间。
(2)然后使用 nohup 命令运行脚本
nohup python3 script.py &
nohup:确保脚本在终端关闭后继续运行。
python3 script.py:运行 Python 脚本。
> script_output.log:将标准输出重定向到 script_output.log 文件。
2> script_error.log:将标准错误输出重定向到 script_error.log 文件。
&:将命令放到后台运行。
(3)检查输出文件
cat script_output.log
结果如下:

(4)验证守护进程
关闭此终端,打开一个新的终端,使用 cat script_output.log 命令查看守护进程是否还在运行

第一个终端关闭后守护进程依旧在运行。
(5)如果需要停止后台运行的脚本,可以使用 kill 命令。首先,找到进程的 PID:
ps -ef | grep python3
![]()
然后使用 kill -9 命令杀掉进程
kill -9 130484(此处为你自己进程的ID号)
2.2 fork() 函数
(1)创建 fork_test.c 文件
nano fork_test.c
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <limits.h> // for _SC_OPEN_MAX
int main() {
pid_t pid = fork();
if (pid < 0) {
// 错误处理:fork失败
perror("fork error");
exit(EXIT_FAILURE);
}
if (pid > 0) {
// 父进程退出
exit(EXIT_SUCCESS);
}
// 子进程继续执行
if (setsid() == -1) {
// 错误处理:setsid失败
perror("setsid error");
exit(EXIT_FAILURE);
}
// 改变当前工作目录
chdir("/");
// 重设文件权限掩码
umask(0);
// 关闭文件描述符
for (int i = 0; i < sysconf(_SC_OPEN_MAX); i++) {
close(i);
}
// 处理信号
signal(SIGCHLD, SIG_IGN);
// 实现守护进程的功能
while (1) {
// 守护进程的业务逻辑
printf("Daemon is running...\n");
sleep(60); // 每隔一段时间执行一次
}
return 0;
}
PS:在 nano 编辑器中,写好代码后 Ctrl + O 保存,再按 Enter 确定,最后 Ctrl + X 退出。
(2)使用 gcc 编译器编译代码
gcc -o fork_test fork_test.c
(3)运行编译后的程序
./fork_test
(4)通过以下命令检查守护进程是否在运行
ps -ef | grep fork_test
结果如下:

(5)验证
关闭此终端重新开一个终端查看进程是否还在运行

2.3 daemon() 函数
(1)创建 daemon_test.c 文件
nano daemon_test.c
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <limits.h> // for _SC_OPEN_MAX
int main() {
// 调用 daemon() 函数创建守护进程
if (daemon(0, 0) == -1) {
// 错误处理:daemon失败
perror("daemon error");
exit(EXIT_FAILURE);
}
// 实现守护进程的功能
while (1) {
// 守护进程的业务逻辑
printf("Daemon is running...\n");
sleep(60); // 每隔一段时间执行一次
}
return 0;
}
(2)编译代码
gcc -o daemon_test daemon_test.c
(3)运行程序
./daemon_test
其余步骤跟fork() 函数创建守护进程相同
二、GDB(GNU Debugger)调试
1.简介
GDB(GNU Debugger)是一个功能强大的开源调试器,广泛用于调试 C、C++ 等编程语言的程序。
2.在阿里云服务器或树莓派上使用 GDB 调试 C 程序
(1)创建一个c语言程序 test.c
nano test.c
代码如下:
#include <stdio.h>
int multiply(int x, int y) {
return x * y;
}
int divide(int x, int y) {
if (y == 0) {
fprintf(stderr, "Error: Division by zero\n");
return 0;
}
return x / y;
}
int main() {
int a = 10, b = 0, c = 20, d;
d = multiply(a, c);
printf("Multiply result: %d\n", d);
d = divide(a, b);
printf("Divide result: %d\n", d);
return 0;
}
(2)编译带调试信息:
使用 -g 选项编译程序,生成调试符号:
gcc -g test.c -o test
(3)启动 GDB 调试:
gdb ./test
(4)设置断点
在函数 multiply 和 divide 中设置断点:
break multiply
break divide
(5)运行程序
输入 run 命令运行程序:
run
(6)检查变量值:
使用 print 命令检查变量的值:
print x
print y
(7)继续执行程序:
使用 continue 命令继续执行程序:
continue
(8)退出 GDB:
完成调试后,使用 quit 命令退出 GDB:
quit
调试过程:

三、SSH反向代理
利用阿里云服务器,使用SSH反向代理,完成树莓派的外网访问。即让其他人可以从任何地方用笔记本电脑,通过访问阿里云服务器的端口(穿透)ssh登录进入你的树莓派系统。
1.确保阿里云对应端口的防火墙关闭,以及GatewayPorts为yes

2.用Putty连接树莓派

3.输入命令搭建ssh通道
ssh -p 22 -qngfNTR 9629:localhost:22 chenqi@114.55.126.125

输入阿里云账号密码
4.在阿里云服务器端查看端口监听状态,命令如下
ss -ntl
端口号在LISTEN就成功了

5.使用另一台电脑打开PowerShell访问树莓派
ssh testuser@114.55.126.125 -p 9629
6.输入树莓派账号密码,成功后如下图所示

至此使用SSH反向代理,完成树莓派的外网访问就完成了,别人可以从任何地方用笔记本电脑,通过访问阿里云服务器的端口(穿透)登录到你的树莓派系统。

2272

被折叠的 条评论
为什么被折叠?



