2012年1月1日星期日

<转载>APUE中第10章信号 程序清单10-14与书上内容不同的说明

这几天做APUE上信号这章的例子,可发现程序10-14编译后 执行结果和书上的有出入,自己想了想问题应该出在静态函数库libapue.a上,以下是静态库中的中间连接文件:
# ar -t libapue.a
bufargs.o
cliconn.o
clrfl.o
daemonize.o
error.o
errorlog.o
lockreg.o
locktest.o
openmax.o
pathalloc.o
popen.o
prexit.o
prmask.o
ptyfork.o
linux_ptyopen.o
readn.o
recvfd.o
senderr.o
sendfd.o
servaccept.o
servlisten.o
setfl.o
signal.o
signalintr.o
sleep.o
sleepus.o
spipe.o
tellwait.o
ttymodes.o
writen.o
我们发现了prmark.o和signal.o,为什么要提到这两个中间文件呢?我来说两句。
如果我们仅仅执行gcc -o a.out 10.14.c libapue.a 不会编译错误,但是我们文件中未含有函数pr_mark()的定义和声明啊?这正是prmark.o存在的效果,此中间文件中含有函数 pr_mark(),所以并不需要我们在执行时将书中关于函数pr_mark()的文件一起编译了。不过不要高兴的太早,这样执行后你就会发现
[root@localhost file1]# ./a.out &
[1] 32035
[root@localhost file1]# starting main:
[root@localhost file1]# kill -USR1 32035
starting sig_usr1:
[root@localhost file1]# in sig_alrm:
finishing sig_usr1:
ending main:
[1]+ Done                    ./a.out
按照书上步骤执行和书上的结果不一样,系统根本就没有为进程打印信号屏蔽字,怪了怎么回事呢?
上网搜了一下发现问题所在了,以下是转载人家的一段文字
终于明白为什么了,太太爽了,今天看APUE无意中脑中想起书上还有这么一句话:”有些系统支持旧的 不可靠语义signal函数,其目的是实现二进制向后兼容“。原来linux就是这样子的,它默认的signal函数就是不可靠语义,所以呢,在调用一次 信号处理函数后会自动设置成默认处理方式而不会再调用了,我把书上的用sigaction实现的signal函数来完成例子果然就一样了!!!
这次给我的教训就是看这本经典著作要十分仔细,里面的每句话都可能暗藏玄机,我以前一直认为linux的sinal就是新式的,原来,。。。。
每个人看书都会不自觉的带入自己想当然的想法,可这往往是错误的,因为我们在还没完全认识事物时会带入自己的想法使之看似合理,其实是不合理的,所以我们要反复的实践,用实践来检验自己的想法。这样才能达到理论和实际的统一!!

我们虽然没有用linux 自带signal 但静态库文件里的signal.o肯定有问题,它就应该时不可靠语意的signal函数。
哈哈,终于知道为什么了!
正确的执行方法是 用sigaction实现的signal函数与10.14.c共同编译
# gcc -o a.out 10.12.c 10.14.c libapue.a
希望对遇到同样问题的朋友有所帮助,小弟以前自发文章很少,表达不清请见谅!