注册
要想使用Signal,首先需要注册Signal的处理函数,就像中断的ISR。最基本的方法是POSIX定义的sigaction()
代码语言:javascript复制typedef unsigned long long sigset_t;
union sigval
{
int sival_int;
void *sival_ptr;
};
typedef struct _Siginfo
{
int si_signo;
int si_code;
union sigval si_value;
} siginfo_t;
struct sigaction
{
union
{
void (*__sa_handler)(int);
void (*__sa_sigaction)(int, siginfo_t *, void *);
} sa_u;
#define sa_handler sa_u.__sa_handler
#define sa_sigaction sa_u.__sa_sigaction
sigset_t sa_mask;
int sa_flags;
};
/*
* POSIX定义的Signal处理函数的安装机制
* sig - Signal number
* pAct - 新的处理函数支持1个参数或3个参数
* pOact - 获得之前的处理函数
*/
int sigaction
(
int sig,
struct sigaction *pAct,
struct sigaction *pOact
);
或者使用简化一些的sigvec()
代码语言:javascript复制typedef unsigned long long sigset_t;
struct sigvec
{
void (*sv_handler)(int);
sigset_t sv_mask;
int sv_flags;
};
/*
* 简化一些的安装机制
* sig - Signal number
* pVec - 新的处理函数支持1个参数
* pOvec - 获得之前的处理函数
*/
int sigvec
(
int sig,
struct sigvec *pVec,
struct sigvec *pOvec
);
而最简单的是直接使用signal()
代码语言:javascript复制/*
* 最简单的安装机制
* sig - Signal number
* pHandler - 处理函数支持1个参数
* 返回值是之前的处理函数
*/
void (*signal(int sig, void(*pHandler)(int)))(int);
等待
注册了Signal之后,这个任务就可以去忙自己的工作了。当相应的Signal被触发后,就会执行注册的函数,所以这个流程是异步的。那如果想同步操作呢?该任务就需要将自己阻塞,等待Signal将其唤醒
最简单的方法是pause()
代码语言:javascript复制/*
* 当前任务进入阻塞状态
* 等待Signal激活
*/
int pause(); /* POSIX */
但有时候不希望被某些Signal打扰,那就使用sigsuspend()将它们屏蔽掉
代码语言:javascript复制typedef unsigned long long sigset_t;
/*
* 功能与pause()类似
* 但忽略pSet指定的Signal
*/
int sigsuspend /* POSIX */
(
sigset_t *pSet
);
甚至有时候不需要使用处理函数
代码语言:javascript复制/*
* 当前任务进入阻塞状态
* 等待pSet指定的Signal激活
* 通常使用sigprocmask()屏蔽其它Signal
*
* 由pSig返回接收到的Signal number
* 并忽略相应Signal的处理函数
*/
int sigwait /* POSIX */
(
sigset_t *pSet,
int *pSig
);
#define SI_SYNC 0 /* (Not posix) gernerated by hardware */
#define SI_USER -1 /* signal from kill() function */
#define SI_QUEUE -2 /* signal from sigqueue() function */
#define SI_TIMER -3 /* signal from expiration of a timer */
#define SI_ASYNCIO -4 /* signal from completion of async I/O */
#define SI_MESGQ -5 /* signal from arrival of a message */
#define SI_CHILD -6 /* signal from child, stopped or terminated */
#define SI_KILL SI_USER
/*
* 功能与sigwait()类似
* 由pInfo->si_signo返回接收到的Signal number
* 由pInfo->si_code返回Signal的触发源
* 由pInfo->si_value返回Queued Signal的Value
*/
int sigwaitinfo
(
sigset_t *pSet,
siginfo_t *pInfo
);
typedef unsigned long time_t;
struct timespec
{
time_t tv_sec;
long tv_nsec;
};
/*
* 功能与sigwait()类似
* 由pTimeout设置超时机制
*/
int sigtimedwait
(
sigset_t *pSet,
siginfo_t *pInfo,
struct timespec *pTimeout
);
触发
那如何产生Signal呢?简单的方法是raise()和kill()
代码语言:javascript复制/*
* 向自己发送一个Signal
*/
int raise
(
int sig
);
/*
* 向tid发送一个Signal
*/
int kill
(
TASK_ID tid,
int sig
);
复杂一点的函数是sigqueue()
代码语言:javascript复制
/*
* 向tid发送一个可以排队的Signal
* 并附带一个value
*/
int sigqueue
(
TASK_ID tid,
int sig,
union sigval value
);
还有一个特殊的封装 - alarm(),详情见《Utility之定时(2)》
代码语言:javascript复制/* 向自己发送SIGALRM */
unsigned int alarm /* POSIX */
(
unsigned int secs
);
最后跑一个最简单的小栗子
我是泰山,专注VX好多年!
一起学习,共同进步!