怀抱观古今,寝食展戏谑。这篇文章主要讲述Android C++系列:Linux信号相关的知识,希望能为你提供帮助。
?
可重入函数
例如:strtok就是一个不可重入函数,因为strtok内部维护了一个内部静态指针,保存上一 次切割到的位置,如果信号的捕捉函数中也去调用strtok函数,则会造成切割字符串混乱, 应用strtok_r版本,r表示可重入。
信号引起的竞态和异步I/O时序竞态
?int pause(void) ?
?
mysleep实现,这种实现方式是否存在BUG??int sigsuspend(const sigset_t *mask) ?
?
#include <
unistd.h>
#include <
signal.h>
#include <
stdio.h>
void sig_alrm(int signo)
/* nothing to do */
unsigned int mysleep(unsigned int nsecs)
struct sigaction newact, oldact;
unsigned int unslept;
newact.sa_handler = sig_alrm;
sigemptyset(&
newact.sa_mask);
newact.sa_flags = 0;
sigaction(SIGALRM, &
newact, &
oldact);
alarm(nsecs);
pause();
unslept = alarm(0);
sigaction(SIGALRM, &
oldact, NULL);
return unslept;
int main(void)
while(1)
mysleep(2);
printf("Two seconds passed\\n");
return 0;
mysleep改进版
unsigned int mysleep(unsigned int nsecs)
struct sigaction newact, oldact;
sigset_t newmask, oldmask, suspmask;
unsigned int unslept;
/* set our handler,save previous information */
newact.sa_handler = sig_alrm;
sigemptyset(&
newact.sa_mask);
newact.sa_flags = 0;
sigaction(SIGALRM, &
newact, &
oldact);
/* block SIGALRM and save current signal mask */
sigemptyset(&
newmask);
sigaddset(&
newmask, SIGALRM);
sigprocmask(SIG_BLOCK, &
newmask, &
oldmask);
alarm(nsecs);
suspmask = oldmask;
sigdelset(&
suspmask, SIGALRM);
/* make sure SIGALRM isnt blocked */
sigsuspend(&
suspmask);
/* wait for any signal to be caught */
/* some signal has been caught,SIGALRM is now blocked */
unslept = alarm(0);
sigaction(SIGALRM, &
oldact, NULL);
/* reset previous action */
/* reset signal mask, which unblocks SIGALRM */
sigprocmask(SIG_SETMASK, &
oldmask, NULL);
return(unslept);
全局变量异步I/O
可重入函数
避免异步I/O的类型
SIGCHLD信号处理SIGCHLD的产生条件
代码实现
#include <
stdio.h>
#include <
stdlib.h>
#include <
unistd.h>
#include <
errno.h>
#include <
sys/types.h>
#include <
sys/wait.h>
#include <
signal.h>
void sys_err(char *str)
perror(str);
exit(1);
void do_sig_child(int signo)
int status;
pid_t pid;
while ((pid = waitpid(0, &
status, WNOHANG)) >
0)
if (WIFEXITED(status))
printf("child %d exit %d\\n", pid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("child %d cancel signal %d\\n", pid, WTERMSIG(status));
int main(void)
pid_t pid;
int i;
//阻塞SIGCHLD
for (i = 0;
i <
10;
i++)
if ((pid = fork()) == 0)
break;
else if (pid <
0)
sys_err("fork");
if (pid == 0)
int n = 18;
while (n--)
printf("child ID %d\\n", getpid());
sleep(1);
return i;
else if (pid >
0)//先设置捕捉
//再解除对SIGCHLD的阻塞
struct sigaction act;
act.sa_handler = do_sig_child;
sigemptyset(&
act.sa_mask);
act.sa_flags = 0;
sigaction(SIGCHLD, &
act, NULL);
while (1)
printf("Parent ID %d\\n", getpid());
sleep(1);
return 0;
status处理方式
??pid_t waitpid(pid_t pid, int *status, int options) ?
?
向信号捕捉函数传参sigqueue
int sigqueue(pid_t pid, int sig, const union sigval value) union sigval
int sival_int;
void *sival_ptr;
;
sigaction
void (*sa_sigaction)(int, siginfo_t *, void *)
siginfo_t
int si_int;
void *si_ptr;
sigval_t si_value;
...
sa_flags = SA_SIGINFO
/* POSIX.1b signal */ /* POSIX.1b signal */ /* Signal value */
实例
信号中断系统调用read阻塞时,信号中断系统调用:
总结【Android C++系列(Linux信号)】本文介绍了可重入函数,信号引起的竞态和异步I/O,SIGCHLD信号处理,向想好捕捉函数传参,信号中断系统调用。
推荐阅读
- Zimbra 管理员如何更新用户邮箱中保存的联系人信息()
- Java SE之基础篇——方法
- Python 分形算法__代码里开出来的艺术之花
- 一文了解 Python 中的迭代器 #私藏项目实操分享#
- K8S陈述式资源管理法
- 小胖学Linux day11(文件的属性及类型)
- Centos7 网络配置
- 9. 利用Docker快速构建MGR | 深入浅出MGR
- 一文了解MySQL的Buffer Pool