apue啃到第十章了,随着内容越来越深入,发现似乎hold不住了,因此在这里记录下我的一些心得
1,signal的函数声明为什么是这样?
如果要返回一个函数指针就需要这么些,至于为什么可以参看:http://blog.csdn.net/zimingjushi/article/details/6554801,这篇文章解释了一些东西,但是依然让人很迷惑:(除了typedef外)没有更简单直观的方法吗?
我觉得这涉及到c语言语法分析的一些东西,以后有时间再仔细研究
2,《不可靠的信号》中的两个例子说明了什么?
a,由于信号动作被复位,嵌套的中断会引起问题
b,如果用户想用pause等待一个信号的话,会丢失掉pause之前就引发的信号,这一段时间可能很重要,此时应该用另一个函数
3,sigaction的陷阱
“sa_sigaction和sa_handler字段的实现可能使用了同一存储区” ,一开始没有注意这句话,结果我在程序中清除了一下sa_sigaction,信号函数死活不能被调用
看了一下声明,它们确实是同一地址:
union { /* Used if SA_SIGINFO is not set. */ __sighandler_t sa_handler; /* Used if SA_SIGINFO is set. */ void (*sa_sigaction) (int, siginfo_t *, void *); }
4,系统调用重启
下面的程序演示了不被重启的效果:
后台模式运行程序,然后kill -USR1 pid,然后fg调到前台运行,结果程序直接返回-1,并不读取任何输入
typedef void (*sigf)(int); inline sigf msignal(int n,sigf f) { struct sigaction act; struct sigaction act1; act.sa_handler=f; act.sa_flags=0; sigemptyset(&act.sa_mask); act.sa_flags|=SA_INTERRUPT; //act.sa_flags|=SA_RESTART; int r=sigaction(n,&act,&act1); printf("r: %d %d\n",r,n); if(r<0)return SIG_ERR; return act1.sa_handler; } static void sig_usr(int sid) { printf("sig: %d\n",sid); } int main() { sigf f1; if((f1=msignal(SIGUSR1,sig_usr))==SIG_ERR)printf("%s\n","err"); if(msignal(SIGUSR2,sig_usr)==SIG_ERR)printf("%s\n","err"); int a='!'; a=getchar(); sprintf("%d %c\n",a,a); //while(a=getchar())putchar(a); return 1; }
4,信号调用不可重入的函数会怎么办?
会引发未知的问题,可能会崩溃,也可能输出错误的答案,我这里运行书上的例子的话,信号getpwnam根本不能返回,但是书上是崩溃(为什么?)
5,SIGCLD的旧语义有什么问题?
设置SIGCLD处理函数会立即检查一下子进程的状态,可能立即调用SIGCLD处理函数,如果在信号处理函数中在wait之前再次设置SIGCLD的话,会引起堆栈溢出
必须在wait之后在重设SIGCLD
6,信号的生命周期:产生-未决-递送,大多数UNIX不对信号进行排队,重复的信号只保留最后一个
7,sleep的实现对alarm的影响,sleep可以选择复位上次设置的alarm,也可以不复位,依赖于实现
在linux上实验,sleep覆盖了原先的alarm没有复位
8,如果不设置SA_NODEFER,在进入信号处理函数后,当前信号被自动加入到信号屏蔽字中,退出函数后复位
这是为了防止同类信号的嵌套处理,这样保证了信号处理函数不会被重入
如果这样的话,10-4节描述的那个问题就不存在了,因为此时不会去处理同一个信号(这主要是旧的不可靠信号的问题)
但是为什么在信号处理函数中再调用raise和kill仍然可以调到本信号的处理函数呢?
9,10-15的代码使用为什么要设置canjump?
为了保证在信号发生时sigsetjump已经被设置