跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C 语言信号处理
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C语言信号处理 = == 介绍 == '''信号(Signal)'''是操作系统用于通知进程发生某种事件的一种机制。在C语言中,信号处理允许程序捕获并响应这些事件,例如用户按下Ctrl+C(SIGINT)或进程尝试访问无效内存(SIGSEGV)。信号处理是系统编程的重要组成部分,尤其在多进程、守护进程或需要优雅退出的程序中。 信号分为两类: * '''标准信号''':如SIGINT(中断)、SIGTERM(终止请求)、SIGKILL(强制终止)等。 * '''实时信号''':如SIGRTMIN到SIGRTMAX,支持排队和携带数据。 == 基本概念 == === 信号的产生 === 信号可以由以下方式产生: * 用户操作(如Ctrl+C发送SIGINT) * 内核检测到异常(如SIGSEGV) * 其他进程通过`kill()`系统调用发送 === 信号的处理方式 === 1. '''默认行为''':如SIGINT默认终止进程。 2. '''忽略信号''':如`signal(SIGINT, SIG_IGN)`。 3. '''自定义处理函数''':通过`signal()`或`sigaction()`注册处理函数。 == 信号处理函数 == === signal() 函数 === `signal()`是传统的信号处理函数,但因其可移植性问题,推荐使用`sigaction()`。 <syntaxhighlight lang="c"> #include <stdio.h> #include <signal.h> #include <unistd.h> void handler(int sig) { printf("Received signal %d\n", sig); } int main() { signal(SIGINT, handler); // 捕获SIGINT(Ctrl+C) while (1) { printf("Running...\n"); sleep(1); } return 0; } </syntaxhighlight> '''输出示例:''' <pre> Running... Running... ^CReceived signal 2 Running... </pre> === sigaction() 函数 === `sigaction()`提供了更精细的控制,是更现代的替代方案。 <syntaxhighlight lang="c"> #include <stdio.h> #include <signal.h> #include <unistd.h> void handler(int sig) { printf("Received signal %d\n", sig); } int main() { struct sigaction sa; sa.sa_handler = handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGINT, &sa, NULL); while (1) { printf("Running...\n"); sleep(1); } return 0; } </syntaxhighlight> == 信号集与阻塞 == 信号可以通过`sigprocmask()`临时阻塞,防止在处理关键代码时被中断。 <syntaxhighlight lang="c"> sigset_t set; sigemptyset(&set); sigaddset(&set, SIGINT); sigprocmask(SIG_BLOCK, &set, NULL); // 阻塞SIGINT // 关键代码 sigprocmask(SIG_UNBLOCK, &set, NULL); // 解除阻塞 </syntaxhighlight> == 实际案例 == === 守护进程的信号处理 === 守护进程通常需要处理SIGHUP(重新加载配置)和SIGTERM(优雅退出)。 <syntaxhighlight lang="c"> void handle_sighup(int sig) { reload_config(); } void handle_sigterm(int sig) { cleanup(); exit(0); } int main() { signal(SIGHUP, handle_sighup); signal(SIGTERM, handle_sigterm); daemonize(); // 主循环 } </syntaxhighlight> === 多线程信号处理 === 在多线程程序中,信号处理需特别注意: * 使用`pthread_sigmask()`控制线程的信号掩码 * 通常由一个专用线程处理所有信号 == 高级主题 == === 信号与竞态条件 === 信号处理函数可能中断主程序的执行,导致竞态条件。解决方法: * 使用`sig_atomic_t`类型声明共享变量 * 在关键代码段阻塞信号 === 实时信号 === 实时信号(SIGRTMIN-SIGRTMAX)支持排队和携带数据: <syntaxhighlight lang="c"> union sigval value; value.sival_int = 42; sigqueue(pid, SIGRTMIN, value); // 发送带数据的信号 </syntaxhighlight> == 常见问题 == {| class="wikitable" |- ! 问题 !! 解决方案 |- | 信号处理函数被中断 || 使用`sigaction()`并设置SA_RESTART标志 |- | 信号丢失 || 使用实时信号或信号队列 |- | 不可靠的信号行为 || 避免在信号处理函数中调用非异步安全函数 |} == 总结 == 信号处理是C语言系统编程的核心概念,用于: * 处理用户中断 * 实现进程间通信 * 构建健壮的守护进程 正确使用信号需要理解其异步特性和潜在陷阱。对于新项目,推荐使用`sigaction()`而非`signal()`,并遵循异步安全编程原则。 <mermaid> graph TD A[信号产生] --> B{处理方式} B --> C[默认行为] B --> D[忽略信号] B --> E[自定义处理] E --> F[signal] E --> G[sigaction] </mermaid> <math> \text{信号延迟} = \frac{\text{信号处理时间}}{\text{CPU时间片}} </math> [[Category:编程语言]] [[Category:C]] [[Category:C 语言系统编程]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)