Signal
基本数据结构和信号掩码说明
信号相关主要数据结构
struct sigactq
{
FAR struct sigactq *flink; /* Forward link */
struct sigaction act; /* Sigaction data */
uint8_t signo; /* Signal associated with action */
};
结构体sigactq用于描述一个信号的action,指针flink将sigactq结构体连接管理,结构体act包含了信号的服务函数和一些控制信息,signo为信号的信号值。为系统注册一个信号,底层将会用一个sigact结构体来描述之
struct sigpendq
{
FAR structsigpendq *flink; /* Forward link */
siginfo_t info; /* Signal information */
uint8_t type; /* (Used to manage allocations) */
};
结构体sigpendq用来描述一个被pend的信号,该信号通过指针flink连接管理,成员info包含信号的详细信息,type被用作该结构体的内存管理信息,用以标识该结构体是从那块内存区域分配的。
struct sigq_s
{
FAR structsigq_s *flink; /* Forward link */
union
{
void (*sighandler)(intsigno, siginfo_t *info, void *context);
} action; /* Signal action */
sigset_t mask; /* Additional signals to mask while the
* the signal-catching function executes */
siginfo_t info; /* Signal information */
uint8_t type; /* (Used to manage allocations) */
};
结构体sigq是信号队列节点,当任务注册了信号,并且接受到了信号,分配一个信号队列节点,将该节点挂载到任务tcb-> sigpendactionq链表上等待运行信号服务函数。指针flink将sigq信号队列节点连接在链表中方便管理,action是一个函数指针,指向信号的服务函数。mask掩码用于当该信号的服务函数运行过程时阻塞其他的信号。Info是信号的详细描述信息。type作为该结构体的内存管理标志,用于标识该结构体从那块内存区域分配的。
在系统初始化过程中,会预先分配sigq_t数据结构、sigpendq_t数据结构和sigactq_t数据结构,并且分别被链接到5个链表上,供后续使用。
g_sigpendingaction
和g_sigpendingirqaction
是sigq资源链表头,用于分配普通sigq资源,而g_sigpendingirqaction
用于在中断中分配sigq资源。
g_sigpendingsignal
和g_sigpendingirqsignal
是sigpend资源链表头,g_sigpendingsignal
用于分配普通的sigpend资源,而g_sigpendingirqsignal
用于在中断中分配sigpend资源。
g_sigfreeaction
是sigact资源链表头,用于分配sigact资源。
tcb中于信号相关的数据结构
struct tcb_s {
…
#ifndef CONFIG_DISABLE_SIGNALS
sigset_t sigprocmask; /* Signals that are blocked */
sigset_t sigwaitmask; /* Waiting for pending signals */
sq_queue_t sigpendactionq; /* List of pending signal actions */
sq_queue_t sigpostedq; /* List of posted signals */
siginfo_t sigunbinfo; /* Signal info when task unblocked */
#endif
…
}
sigprocmask是该任务tcb阻塞信号集。如果某个信号属于阻塞信号集,那么如果发送信号到该tcb,信号将被阻塞,除非该信号是该任务等待的信号,或者该任务取消对该信号的阻塞。
sigwaitmask是该任务等待的信号集。
sigpendactionq链表用于挂载该任务将要服务的信号节点sigq,等到合该任务开始运行时,sigpendactionq上的节点所代表的信号的服务函数将被运行。信号服务函数运行前,该信号的sigq节点将从sigpendactionq链表上转移到sigpostedq链表上。
sigpostedq链表上挂载正在执行信号服务函数的信号节点sigq。当信号服务函数返回后,信号节点sigq将被移除sigpostedq,然后被释放。
当任务等到它所等待的信号sigunbinfo用于记录信号信息。
task_group中信号相关的数据结构
struct task_group_s {
…
#ifndef CONFIG_DISABLE_SIGNALS
/* POSIX Signal Control Fields ************************************************/
sq_queue_t tg_sigactionq; /* List of actions for signals */
sq_queue_t tg_sigpendingq; /* List of pending signals */
#endif
…
}
- tg_sigactionq链表用于记录注册到某个任务tcb的信号。
- tg_sipendingq链表用于记录某个任务tcb接收到的信号。
注册一个信号,即是将关联某个任务tcb与某个信号的服务函数。当任务接收到信号后,对应信号的服务函数期望被运行。这里注意,注册的信号对应的sigact是挂载在任务tcb->group结构体中的sg_sigactionq链表中的,而非任务tcb中。任务tcb接收到的信号sigpend也被挂载到任务tcb->group结构体重的sg_sigpendingq链表中。
信号的种类
Nuttx支持32个信号,最小的信号值为SIGRTMIN,其值为0,最大的信号值为SIGRTMAX,其值为31。使用一个32bit的整形变量,其中的每一个bit的值用来标志一个对应的信号。部分信号值定义如下,其余信号用户可以自定义。
#define SIGUSR1 1 // for user signal 1
#define SIGUSR2 2 // for user signal 2
#define SIGALRM 3 // default signal used with POSIX timer
#define SIGCHILD 4 // used for child thread to signal parent thread
#define SIGPOLL 5 // sent when asynchronous I/O event occurs
#define SIGCONDTIMEDOUT 16 // used in the implementation of pthread_cond_timedwait
#define SIGWORK 17 // used to wake up the work queue
信号动作标志
信号动作标志用于指示该信号动作相关的信息。
#define SA_NOCLDSTOP (1<<0)
#define SA_SIGINFO (1<<1)
#define SA_NOCLDWAIT (1<<2)
- SA_NOCLDSTOP用于指示进程,当子进程退出时,不要产生SIGCHILD。
- SA_SIGINFO指示,当收到信号后,信号动作服务函数使用三个参数,而不是一个参数。
- SA_NOCLDWAIT指示,当信号值为SIGCHLD时,不予对子进程退出状态的处理。
信号处理掩码方式
信号处理掩码方式决定了对于特定的信号值,任务如何对待这些信号。
#define SIG_BLOCK 1
#