嵌入式Linux C语言笔记——信号

目录

信号产生的条件

信号的处理方式

信号的异步性质

信号的一些常见的操作

signal()

sigaction()

raise()

kill()

sigprocmask()

sigpending()

sigwait()


类别 描述
信号的定义 信号是事件发生时对进程的通知机制,可以理解为软件中断,通常用于处理异步事件。
信号与硬件中断的相似性 信号与硬件中断相似,能够打断程序的正常流程,通知进程处理特定的事件。
信号的作用 用于进程间通信(IPC)和同步。信号通过通知进程某些事件的发生,进而影响进程的行为。

信号产生的条件

条件 说明
硬件异常 例如除数为 0、访问非法内存等,硬件检测到异常后由内核向进程发送信号。
终端输入 用户通过按键(如 CTRL + C、CTRL + Z 等)触发的信号。
进程调用 kill() 进程可以使用 kill() 系统调用向另一个进程发送信号,前提是进程具有合适的权限。
用户使用 kill 命令 用户在终端使用 kill 命令发送信号给其他进程,例如使用 kill -9 <pid> 来终止进程。
软件事件 进程执行过程中,系统检测到某些事件发生时(如定时器超时、CPU 时间限制等),内核向进程发送信号。

信号的处理方式

处理方式 说明
忽略信号 进程选择忽略某些信号。大多数信号可以被忽略,但 SIGKILLSIGSTOP 不能被忽略。忽略某些硬件异常信号会导致未定义的行为。
捕获信号 进程注册一个自定义的信号处理函数,在信号到达时,内核会调用该函数处理信号。可以使用 signal() 系统调用来注册信号处理函数。
执行系统默认操作 当进程不处理信号时,系统会执行该信号的默认操作。大多数信号的默认操作是终止进程,除非是 SIGKILLSIGSTOP

信号的异步性质

特性 说明
异步事件 信号是异步事件,进程无法预测信号的确切时间,信号的到来是随机的,类似于硬件中断。进程无法通过简单的变量测试或系统调用判断是否会发生信号,只有当信号到达时,才会中断当前进程的执行。
复制代码
/* 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). */ 
信号名称 说明 默认操作
SIGINT 当用户按下 CTRL + C 时,内核将发送该信号给前台进程组中的进程。 终止进程
SIGQUIT 当用户按下 CTRL + \ 时,内核将发送该信号给前台进程组中的进程。 终止进程并生成核心转储文件
SIGILL 进程执行非法的机器指令时,内核发送该信号。 终止进程
SIGABRT 当进程调用 abort() 系统调用时,发送该信号。 终止进程并生成核心转储文件
SIGBUS 进程发生总线错误(内存访问错误)时,内核发送该信号。 终止进程
SIGFPE 进程发生算术错误时(如除零),内核发送该信号。 终止进程
SIGKILL 进程无法阻塞、忽略或捕获该信号。用于强制终止进程。 终止进程
SIGUSR1 用户自定义信号,通常用于进程间通信或同步。 终止进程
SIGSEGV 进程对无效内存引用时,内核发送该信号。 终止进程
SIGUSR2 用户自定义信号,通常与 SIGUSR1 一样使用。 终止进程
SIGPIPE 当进程向已关闭的管道、FIFO 或套接字写入时,内核发送该信号。 终止进程
SIGALRM 当定时器到期时,内核通过 alarm()setitimer() 系统调用发送该信号。 终止进程
SIGTERM 默认终止进程的信号,也常通过 kill 命令发送。 终止进程(进程可捕获并清理资源)
SIGCHLD 当子进程终止或状态发生变化时,内核发送该信号给父进程。 忽略信号
SIGCLD SIGCHLD,是同义词。 忽略信号
SIGCONT 发送给停止状态的进程,恢复其运行。 恢复进程运行(如果进程处于停止状态)
SIGSTOP 强制停止进程,无法被忽略或捕获。 停止进程
SIGTSTP 当用户按下 CTRL + Z 时,内核将发送该信号使进程停止。 停止进程
SIGXCPU 当进程的 CPU 时间超出资源限制时,内核发送该信号。 终止进程
SIGVTALRM 应用程序通过 setitimer() 设置虚拟定时器时,定时器到期时发送该信号。 终止进程
SIGWINCH 当终端窗口尺寸发生变化时(例如用户调整大小或应用程序调用 ioctl() 设置),内核发送该信号。 终止进程
SIGPOLL/SIGIO 当异步 I/O 事件发生时,内核发送该信号。 终止进程
SIGSYS 当进程发起的系统调用错误时,内核发送该信号。 终止进程

信号的一些常见的操作

signal()

原型

复制代码
void (*signal(int signum, void (*handler)(int)))(int);

说明

  • signal() 用于指定一个信号的处理函数,当信号到达时,操作系统会调用该处理函数。

  • 第一个参数 signum 是需要处理的信号的编号(如 SIGINT, SIGTERM 等)。

  • 第二个参数handler是信号处理函数的指针,用户可以自定义该函数以处理特定信号。

    • 如果 handlerSIG_IGN,表示忽略该信号。

    • 如果 handlerSIG_DFL,表示恢复默认的信号处理行为。

  • 返回值是之前信号处理函数的地址,可以用来恢复原始信号处理。

注意

  • signal() 是一个相对简化的接口,不适合处理复杂的信号处理需求,且其行为在不同的系统中可能有所不同。

  • 在现代系统中,推荐使用 sigaction() 替代 signal(),因为 sigaction() 提供了更多的控制选项。

sigaction()

原型

复制代码
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

说明

  • sigaction() 用于更精细地控制信号的处理。它允许用户指定信号处理程序、处理程序的行为、以及如何恢复原来的信号处理行为。

  • 第一个参数 signum 是信号编号。

  • 第二个参数act是一个指向struct sigaction的指针,该结构体定义了信号处理程序的详细信息。

    • sa_handler:信号处理函数的指针。

    • sa_mask:一个信号集,表示在信号处理程序执行期间要阻塞的信号。

    • sa_flags:指定信号处理程序的行为。常见的标志包括 SA_RESTART(使得系统调用在被信号打断后自动重启)和 SA_SIGINFO(启用额外的信号信息传递)。

  • 第三个参数 oldact 是一个指向 struct sigaction 的指针,用于保存原来的信号处理设置,以便稍后恢复。

返回值

  • 成功时返回 0,失败时返回 -1,并设置 errno

raise()

原型

复制代码
int raise(int signum);

说明

  • raise() 用于向当前进程发送一个信号。它将信号发送到当前进程的进程组中。

  • 参数 signum 是要发送的信号编号。

  • 返回值:成功时返回 0,失败时返回 -1,并设置 errno

kill()

原型

复制代码
int kill(pid_t pid, int signum);

说明

  • kill() 用于向指定进程或进程组发送信号。即使是向自己的进程发送信号,它也能有效地触发信号的处理。

  • 参数pid是目标进程的 PID:

    • 如果 pid > 0,发送信号给指定的进程。

    • 如果 pid == 0,发送信号给与当前进程属于同一进程组的所有进程。

    • 如果 pid == -1,发送信号给所有进程(需要超级用户权限)。

    • 如果 pid < -1,发送信号给指定进程组的所有进程。

  • 参数 signum 是信号编号(如 SIGINT, SIGTERM 等)。

  • 返回值:成功时返回 0,失败时返回 -1,并设置 errno

sigprocmask()

原型

复制代码
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

说明

  • sigprocmask() 用于控制进程的信号屏蔽字,屏蔽字表示进程在处理信号时哪些信号应被暂时阻塞。

  • 参数how定义了操作方式:

    • SIG_BLOCK:将信号集中的信号加入到当前的信号屏蔽字中。

    • SIG_UNBLOCK:从当前屏蔽字中删除信号集中的信号。

    • SIG_SETMASK:将信号集设置为指定的信号集。

  • 参数 set 是一个信号集,包含要屏蔽或解除屏蔽的信号。

  • 参数 oldset 用于保存操作前的信号屏蔽字。

sigpending()

原型

复制代码
int sigpending(sigset_t *set);

说明

  • sigpending() 用于检查当前进程是否有被屏蔽但尚未处理的信号。

  • 参数 set 是一个信号集,函数会将所有挂起的信号保存到该信号集。

  • 返回值:成功时返回 0,失败时返回 -1,并设置 errno

sigwait()

原型

复制代码
int sigwait(const sigset_t *set, int *signo);

说明

  • sigwait() 用于同步地等待一个指定信号集中的信号到达,并阻塞直到接收到该信号。

  • 参数 set 是一个信号集,指定了进程要等待的信号。

  • 参数 signo 用于返回接收到的信号编号。

  • 返回值:返回 0 表示成功,返回 -1 表示错误,errno 设置为相应的错误码。

相关推荐
听风吟丶3 分钟前
《深入理解 Java 中的 ImmutableList》
java·开发语言
hacker7075 分钟前
Datawhale AI冬令营学习笔记--定制你的专属大模型
人工智能·笔记·学习
社畜码农且逊17 分钟前
Ubuntu22.04搭建FTP服务器保姆级教程
linux·运维·服务器
坐井观老天18 分钟前
使用WPF和C#绘制覆盖网格的3D表面
开发语言·c#·wpf
inter_peng21 分钟前
[工具升级问题] 钉钉(linux版)升级带来的小麻烦
linux·运维·钉钉
羽球知道25 分钟前
scala正则表达式特点方法
开发语言·正则表达式·scala
Mr.王83533 分钟前
架构学习第六周--Kubernetes(二)
linux·架构·kubernetes
Kemo_33 分钟前
Java:主要特点、应用领域、架构工具、未来
java·开发语言·架构
冷眼看人间恩怨1 小时前
【C++】关联存储结构容器-set(集合)详解
开发语言·c++·set
٩( 'ω' )و2601 小时前
SList(单链表)
c语言·数据结构