文章目录
- 1. kill - send signal to a process
- 2. raise - send a signal to the caller
- 3. abort - cause abnormal process termination
- 4.alarm - set an alarm clock for delivery of a signal
- 5. getitimer, setitimer - get or set value of an interval timer
- 6. signal - ANSI C signal handling
- 7. 信号集操作函数
- 8. sigaction - examine and change a signal action
- 9. 竞态条件(时序竞态)
- 10.SIGCHLD信号
1. kill - send signal to a process
int kill(pid_t pid, int sig);
2. raise - send a signal to the caller
int raise(int sig);
给当前进程发送信号,自己给自己发送指定的信号
3. abort - cause abnormal process termination
void abort(void);
给自己发送异常终止信号。
4.alarm - set an alarm clock for delivery of a signal
unsigned int alarm(unsigned int seconds);
设置定时器(闹钟),到时间点后发送SIGALARM,默认动作为终止。
返回值为之前的闹钟剩余的时间。
$ time ./test
real 0m0.027s
user 0m0.000s
sys 0m0.024s
实际执行时间 = 系统时间+用户时间+等待时间
5. getitimer, setitimer - get or set value of an interval timer
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
设置定时器,可以替代alarm函数,精确到微妙,可以周期定时。
参数:which:指定定时方式
1.ITIMER_REAL:自然定时 ,计算自然时间,发出SIGALARM信号
2.ITIMER_VIRTUAL 虚拟空间计时, 用户空间时间,发出SIGVTALARM信号,只计算进程占用cpu的时间
3.ITIMER_PROF 运行时计时,用户+内核 ,发出SIGPROF信号,计算占用cpu和执行系统调用的时间
6. signal - ANSI C signal handling
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
注册一个信号的捕捉处理函数。
7. 信号集操作函数
内核通过读取未决信号集来判断信号是否应被处理。
信号屏蔽字可以影响信号集。
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
sigemptyset() initializes the signal set given by set to empty, with all signals excluded from the set.
sigfillset() initializes set to full, including all signals.
sigaddset() and sigdelset() add and delete respectively signal signum from set.
sigismember() tests whether signum is a member of set.
sigprocmask - examine and change blocked signals
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
sigpending - examine pending signals 读取 未决信号集
int sigpending(sigset_t *set);
void printped(sigset_t *ped)
{
int i;
for(i=1;i<32;i++){
if(sigismember(ped, i) == 1)
putchar('1');
else
putchar('0);
}
}
int main(void)
{
sigset_t myset, oldset, ped;
sigemptyset(&myset);
sigaddset(&myset, SIGQUIT);
sigprocmask(SIG_BLOCK, &myset, &oldset);
while(1) {
sigpending(&ped);
printped(&ped);
sleep(1);
}
}
8. sigaction - examine and change a signal action
void docatch(int signo)
{
printf("%d\n", signo);
}
int main(void)
{
int ret;
struct sigation act;
act.sa_handler = docatch;
sigaddset(&act.sa_mask, SIGQUIT);//sa_mask:调用信号处理函数时,所要屏蔽的信号集合(信号屏蔽字)。注意:仅在处理函数被调用期间生效,是临时的设置。
act.sa_flag = 0;//默认属性。信号捕捉函数执行期间,自动屏蔽此信号。
ret = sigaction(SIGINT, &act, NULL);
if(ret < 0)
exit(1);
}
9. 竞态条件(时序竞态)
9.1 pause
调用该函数可以造成进程主动挂起,等待信号唤醒。调用该系统调用的进程处于阻塞状态(主动放弃cpu),直到有信号抵达将其唤醒。
int pause(void);
返回值:-1 并设置errno 为EINTR
9.2 sigsuspend
可以通过设置屏蔽SIGALARM的方式来控制程序执行的逻辑,但无论如何设置,程序都有可能在,解除信号屏蔽与挂起等待信号,这两个操作间隙失去cpu。除非将这两个步骤合并成一个原子操作,sigsuspend函数具备这个功能。在对时序要求严格的场合下应该使用sigsuspend替换pause。
int sigsuspend(const sigset_t *mask);
函数调用期间,进程信号屏蔽字由其参数mask指定。
9.3 可重入函数/不可重入函数
注意事项:
1.定义可重入函数,函数内部不能含有全局变量和static变量,不能使用malloc、free函数
2.信号捕捉函数应设计为可重入函数
3.信号处理程序可以调用的可重入函数可参阅man 7 signal
4.没有包含在上述列表中的函数大多是不可重入的函数,其原因为:
a>使用了静态的数据结构
b>调用了malloc或free
c>是标准的I/O函数
10.SIGCHLD信号
产生条件:
- ·子进程终止时。
- 子进程接收到SIGSTOP信号停止时。
- 子进程处在停止状态,接受到SIGCONT后唤醒时。