信号
信号的发送者、接收者都是线程,线程对收到的信号,有三类处理方式:第一类:类似中断处理程序,对于需要处理的信号,线程可以指定处理函数,由该函数处理;第二类:忽略某个信号,对该信号不处理;第三类:对该信号的处理,使用系统的默认方式。可以通过给信号安装处理函数的方式来选择处理方式
rt_signal_install(SIGUSR1, my_signal_handler); /* 给信号 SIGUSR1 安装我们自己的处理函数 */
rt_signal_install(SIGUSR1, SIG_IGN); /* 不处理信号 SIGUSR1 */
rt_signal_install(SIGUSR1, SIG_DFL); /* 给信号 SIGUSR1 安装默认的处理函数,只是打印 */
RT-Thread 根据 POSIX 标准定义信号集,大部分信号被系统所用,用户程序只能使用SIGUSR1(10)和 SIGUSR2(12)。
假设有两个线程,线程 1 接收信号,线程 2 发送信号,用法如下:
- 线程 1 先安装信号并设置对信号的处理方式,然后解除阻塞
/* 安装信号,自定义处理函数 */
rt_signal_install(SIGUSR1, my_signal_handler);
/* 解除阻塞 */
rt_signal_unmask(SIGUSR1);
- 线程 2 发送信号,触发线程 1 进行处理
rt_thread_kill(thread1, SIGUSR1); //向线程 1 发送信号 SIGUSR1
如果线程1在挂起状态收到信号:线程 1 被唤醒,线程 1 先调用信号处理函数,再继续运行之前的代码
如果线程1在就绪状态收到信号:线程 1 再次运行时,先调用信号处理函数,再继续运行之前的代码。
使用信号时,需要有安装、屏蔽/使能、发送和等待几个动作
安装:如果线程需要处理某一个信号,就需要现在线程中安装该信号。安装函数的用法如下:
rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler);
signo:信号值(SIGUSR1 或 SIGUSR2)
handler:处理方式(SIG_IGN、SIG_DFL、自定义处理函数)
SIG_IGN,就是忽略:接收到信号后不做任何处理
SIG_DFL,即使用系统的默认方式,系统会调用默认的处理函数_signal_default_handler(),它只是打印
屏蔽/使能:如果屏蔽该信号,就该信号不会传达给安装该信号的线程。屏蔽信号的函数原型如下:
void rt_signal_mask(int signo);
即使能信号的函数原型如下:
void rt_signal_unmask(int signo);
发送信号:当需要某线程进行异常处理时,如果该线程安装了某信号,则使用 rt_thread_kill()发送信号,函数原型如下:
int rt_thread_kill(rt_thread_t tid, int sig)
tid:接收信号的线程
sig:信号值
等待信号:一个线程可以等待别的线程给它发信号,函数原型如下:
int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout);
set:输入参数:想等待哪个信号,注意它是一个指针,*set 等于信号的编号
si:输出参数:用来保存等到的信号的信息