下面分别给出一个 Shell 脚本和 C 程序的例子,实现通过 Shell 脚本发送信号给 C 应用程序,让 C 应用程序回收线程资源后自行退出。
原理
在 Linux 系统中,我们可以使用信号机制来实现进程间的通信。Shell 脚本可以使用 kill
命令向指定的进程发送信号,而 C 程序可以使用 signal
或 sigaction
函数来捕获这些信号,并在信号处理函数中进行线程资源的回收和程序的退出操作。
C 程序示例
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
// 全局变量,用于标记是否收到终止信号
volatile sig_atomic_t terminate = 0;
// 线程函数
void *thread_function(void *arg) {
while (!terminate) {
printf("线程正在运行...\n");
sleep(1);
}
printf("线程收到终止信号,开始清理资源...\n");
// 这里可以添加更多的资源清理代码
pthread_exit(NULL);
}
// 信号处理函数
void signal_handler(int signum) {
if (signum == SIGTERM) {
printf("收到 SIGTERM 信号,开始终止程序...\n");
terminate = 1;
}
}
int main() {
pthread_t thread;
// 注册信号处理函数
signal(SIGTERM, signal_handler);
// 创建线程
if (pthread_create(&thread, NULL, thread_function, NULL) != 0) {
perror("线程创建失败");
return 1;
}
// 等待线程结束
pthread_join(thread, NULL);
printf("所有线程资源已回收,程序退出...\n");
return 0;
}
代码解释
- 全局变量
terminate
:用于标记是否收到终止信号,volatile sig_atomic_t
确保在多线程环境下该变量的访问是原子的。 - 线程函数
thread_function
:在一个循环中持续运行,直到terminate
变为 1,表示收到终止信号,然后进行资源清理并退出线程。 - 信号处理函数
signal_handler
:当收到SIGTERM
信号时,将terminate
标记为 1,通知线程停止运行。 - 主函数
main
:注册信号处理函数,创建线程,并等待线程结束。
Shell 脚本示例
#!/bin/bash
# 编译 C 程序
gcc -o my_program my_program.c -lpthread
# 启动 C 程序
./my_program &
pid=$! # 获取 C 程序的 PID
# 等待一段时间
sleep 5
# 发送 SIGTERM 信号给 C 程序
kill -SIGTERM $pid
# 等待 C 程序退出
wait $pid
echo "C 程序已退出"
代码解释
- 编译 C 程序 :使用
gcc
编译 C 程序,并生成可执行文件my_program
。 - 启动 C 程序 :使用
&
符号将 C 程序放到后台运行,并使用$!
获取其 PID。 - 等待一段时间 :使用
sleep
命令等待 5 秒,让 C 程序有足够的时间运行。 - 发送信号 :使用
kill -SIGTERM
命令向 C 程序发送SIGTERM
信号。 - 等待程序退出 :使用
wait
命令等待 C 程序退出,并打印退出信息。
运行步骤
- 将上述 C 代码保存为
my_program.c
,将 Shell 脚本保存为send_signal.sh
。 - 给 Shell 脚本添加执行权限:
chmod +x send_signal.sh
。 - 运行 Shell 脚本:
./send_signal.sh
。
通过以上步骤,你可以看到 Shell 脚本成功发送信号给 C 程序,C 程序在收到信号后回收线程资源并退出。