背景和需求
- Linux环境中,有一个可执行程序,假设该程序的运行生命周期需要调用下面四个函数:
int connect();
int start();
int end();
int disconnect();
如果用户在程序运行期间,手动CTRL+C
或关闭终端
来停止程序,则会造成错误。
- 所以需要在程序被用户手动关闭或程序意外退出的时候,调用
int end();
和int disconnect();
函数。
解决方法
在C++中,可以使用信号处理函数来捕获用户通过CTRL+C等操作关闭程序的信号,并在信号处理函数中调用相应的函数。
举例:
#include <iostream>
#include <csignal>
std::shared_ptr<RpcClient> rpc;
// 定义信号处理函数
void signalHandler(int signal)
{
if (signal == SIGINT || signal == SIGQUIT || signal == SIGHUP) {
std::cout << "Received SIGINT signal." << std::endl;
rpc->end();
rpc->disconnect();
// 退出程序
exit(0);
}
}
int main() {
// 注册信号处理函数
// 中断信号,通常由用户在终端上按下Ctrl+C引发
signal(SIGINT, signalHandler);
// 退出信号,通常由用户在终端上按下Ctrl+\引发
signal(SIGQUIT, signalHandler);
// 挂起信号,通常由终端断开或控制进程终止引发
signal(SIGHUP, signalHandler);
// 程序主逻辑
// 创建 RpcClient 对象
rpc = std::make_shared<RpcClient>();
rpc->connect();
rpc->start();
// 程序运行中...
rpc->end();
rpc->disconnect();
return 0;
}
关于信号类型
这段代码定义了一系列信号的常量值。每个信号都有一个唯一的整数值来表示。这些信号用于在程序执行过程中与操作系统进行通信,例如处理异常情况或接收外部事件。
/* Signals. */
#define SIGHUP 1 /* Hangup (POSIX). */
#define SIGINT 2 /* Interrupt (ANSI). */
#define SIGQUIT 3 /* Quit (POSIX). */
#define SIGILL 4 /* Illegal instruction (ANSI). */
#define SIGTRAP 5 /* Trace trap (POSIX). */
#define SIGABRT 6 /* Abort (ANSI). */
#define SIGIOT 6 /* IOT trap (4.2 BSD). */
#define SIGBUS 7 /* BUS error (4.2 BSD). */
#define SIGFPE 8 /* Floating-point exception (ANSI). */
#define SIGKILL 9 /* Kill, unblockable (POSIX). */
#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */
#define SIGSEGV 11 /* Segmentation violation (ANSI). */
#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */
#define SIGPIPE 13 /* Broken pipe (POSIX). */
#define SIGALRM 14 /* Alarm clock (POSIX). */
#define SIGTERM 15 /* Termination (ANSI). */
#define SIGSTKFLT 16 /* Stack fault. */
#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */
#define SIGCHLD 17 /* Child status has changed (POSIX). */
#define SIGCONT 18 /* Continue (POSIX). */
#define SIGSTOP 19 /* Stop, unblockable (POSIX). */
#define SIGTSTP 20 /* Keyboard stop (POSIX). */
#define SIGTTIN 21 /* Background read from tty (POSIX). */
#define SIGTTOU 22 /* Background write to tty (POSIX). */
#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */
#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */
#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */
#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */
#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */
#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */
#define SIGPOLL SIGIO /* Pollable event occurred (System V). */
#define SIGIO 29 /* I/O now possible (4.2 BSD). */
#define SIGPWR 30 /* Power failure restart (System V). */
#define SIGSYS 31 /* Bad system call. */
#define SIGUNUSED 31
以下是一些常见信号的说明:
- SIGHUP(1):挂起信号,通常由终端断开或控制进程终止引发。
- SIGINT(2):中断信号,通常由用户在终端上按下Ctrl+C引发。
- SIGQUIT(3):退出信号,通常由用户在终端上按下Ctrl+\引发。
- SIGILL(4):非法指令信号,通常由非法的机器指令引发。
- SIGABRT(6):异常终止信号,通常由调用abort函数引发。
- SIGFPE(8):浮点异常信号,通常由浮点运算错误引发。
- SIGKILL(9):强制终止信号,无法被阻塞、处理或忽略。
- SIGSEGV(11):段错误信号,通常由非法内存访问引发。
- SIGPIPE(13):管道破裂信号,通常由写入已关闭的管道引发。
- SIGALRM(14):闹钟信号,通常由调用alarm函数引发。
- SIGTERM(15):终止信号,通常用于请求程序正常终止。