免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4677 | 回复: 8

[内核入门] SIGALRM信号处理异常 [复制链接]

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2014-04-18 23:07 |显示全部楼层
最近学习,用到了alarm的信号处理。照着书抄写了代码,但是发现,在执行了信号处理函数之后,就挂死在哪里了,是我代码问题还是系统问题?
下面是我写的代码:
  1. #include <signal.h>
  2. #include <unistd.h>
  3. #include <stdio.h>

  4. void sig_alarm(int )
  5. {
  6.     printf("==========alarm clock!==============\n");
  7. }
  8. void test_alarm()
  9. {
  10.     alarm(3);
  11.     char buf[1024] = {0};
  12.     int len = read(STDIN_FILENO,buf,1024);
  13.     alarm(0);
  14.     printf("test alarm succed!\n");
  15. }

  16. int main()
  17. {
  18.     signal(SIGALRM,sig_alarm);
  19.     test_alarm();
  20.     return 0;
  21. }
复制代码
gstac查看进程信息,发现挂死在__kernel_vsyscall,情况如下:
  1. [knull@knull sock_raw]$ gstack 5212
  2. #0  0x009b0424 in __kernel_vsyscall ()
  3. #1  0x00c0c8c3 in __read_nocancel () from /lib/libc.so.6
  4. #2  0x08048563 in test_alarm() ()
  5. #3  0x080485aa in main ()
复制代码
我的系统版本是CentOS release 6.5 (Final)
编译器版本是gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
发表于 2014-04-21 10:24 |显示全部楼层
回复 1# knull

int len = read(STDIN_FILENO,buf,1024);

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2014-04-21 19:37 |显示全部楼层
asuka2001 发表于 2014-04-21 10:24
回复 1# knull

int len = read(STDIN_FILENO,buf,1024);

哥哥,不是很明白啊,请讲明白点,谢谢

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
发表于 2014-04-21 23:12 |显示全部楼层
回复 3# knull

你这里要从标准输入读入数据,自然阻塞了!

你试试随便输入点东西回车看看!

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2014-04-24 14:27 |显示全部楼层
asuka2001 发表于 2014-04-21 23:12
回复 3# knull

你这里要从标准输入读入数据,自然阻塞了!


这是我书上抄来的代码,就是测试“alarm”这个功能的。
read读不到数据,
alarm(3)--->导致3秒超时;
超时会走到sig_alarm中去(注册的信号处理函数)。
但是,书上的说法,看起来sig_alarm执行完了之后,会回到read后面(因为这里sig_alarm没做任何事情,没有退出)

论坛徽章:
0
发表于 2014-04-24 15:33 |显示全部楼层

回复 3# knull

你这里要从标准输入读入数据,自然阻塞了!

你试试随便输入点东西回车看看!


以上回答是正确的   自己可以试一下

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2014-04-27 16:50 |显示全部楼层
yanzhaozhiqing 发表于 2014-04-24 15:33
回复 3# knull

你这里要从标准输入读入数据,自然阻塞了!

谢谢你的回复;我试过了,你是对的。
我之前只关注了“alarm”,而原因是在read,而我又死jiang,所以一直没找到眼前的答案。
另外问一个问题:
我看《UNIX网络编程》,原始套接字那章(28),traceroute示例代码,就是用alarm来做定时器的:
recvfrom读原始套接字fd,alarm作为3秒定时器,如果alarm超时,那么就sig_alarm处理,置标志位;
我拿他的代码测试了,发现是同样的问题:read那卡死了;
那么,是书上代码错误,还是我有没注意的地方?
后来我改用select+超时,可以达到同样的效果;

论坛徽章:
0
发表于 2014-12-17 22:36 |显示全部楼层
我有一个疑问,当产生了信号,read函数不是应该会返回EGINT错误的吗?会为什么read函数还是阻塞。怎么和书上说的不一样

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2015-07-26 16:32 |显示全部楼层
今天重新看APUE信号处理那章节,系统调用中有一些是可重入的(相对于“信号处理”而言),而read函数正好就是可重入函数。
这样就明白了:
1、在alarm(3)之后,调用read阻塞在那;
2、在3秒之后,产生alarm信号,于是到注册的自定义信号处理函数;
3、信号处理函数结束之后,由于read是可重入的系统调用函数,于是,就又回到的read的系统调用上。

结论:上述代码,是实现“超时功能的read函数”,但是,却并没有达到超时的效果。所以,这个代码例子本身就是错误的。
(可能,第一版本的时候,read还不是可重入函数;但是,后期第二版本的时候,read被加入到可重入的函数中去了,但是对应的代码没有做修正)
参考:APUE2—10.6:可重入函数;
         APUE2—10.10:alarm和pause函数;中间有一个超时的read函数代码例子。

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP