免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5245 | 回复: 9
打印 上一主题 下一主题

[C] 请问:read函数如何被信号中断 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-07-11 11:22 |只看该作者 |倒序浏览
我想让read函数在没有输入的情况下,3秒后被时钟中断,请问该怎么做?(我的程序read不会被中断,
只是到了3秒会输出提示,但read函数还是在等待)
请看:
void handler(int sig)
{
        printf("recv a sig=%d\n",sig);
}
int main()
{
        signal(SIGALAM,handler);
        alarm(3);
        char buf[1024];
        int ret;
        ret=read(0,buf,sizeof(buf));
        if(ret==-1)
        {
                printf("interrupt by alarm signal\n");
        }
        return 0;
       
}

论坛徽章:
0
2 [报告]
发表于 2016-07-11 13:55 |只看该作者
sigjmp_buf jmp_env;

void handler(int sig)
{
        //printf("recv a sig=%d\n",sig);
        siglongjmp(jmp_env, 1);
}
int main()
{
        signal(SIGALRM,handler);
        alarm(3);
        if (sigsetjmp(jmp_env, 1))  
        {  
                alarm(0);
                    goto out;  
               }  
        char buf[1024];
        int ret;
        ret=read(0,buf,sizeof(buf));
        
        signal(SIGALRM,SIG_IGN);/*成功的话就忽略错误超时信号*/
        
        if(ret==-1)
        {
                printf("interrupt by alarm signal\n");
        }
        out:
                exit(0);
        return 0;
        
}
应该可以..

论坛徽章:
0
3 [报告]
发表于 2016-07-11 15:37 |只看该作者
程序退出了,但是没有输出 printf("interrupt by alarm signal\n");
请问:为什么?怎么办?

        

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
4 [报告]
发表于 2016-09-30 14:48 |只看该作者
我曾经问过这个类似的问题(《UNIX环境高级编程》信号处理章节 的一个例子,这是链接:http://bbs.chinaunix.net/thread-4135617-1-1.html
没有找到官方、标准答案。我自己猜测了一个答案:
重新看APUE信号处理那章节,系统调用中有一些是可重入的(相对于“信号处理”而言),而read函数正好就是可重入函数。
这样就明白了:
1、在alarm(3)之后,调用read阻塞在那;
2、在3秒之后,产生alarm信号,于是到注册的自定义信号处理函数;
3、信号处理函数结束之后,由于read是可重入的系统调用函数,于是,就又回到的read的系统调用上。

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

论坛徽章:
1
数据库技术版块每日发帖之星
日期:2016-08-14 06:20:00
5 [报告]
发表于 2016-11-15 23:17 |只看该作者
用select的超时功能呢?类似:
fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);
timeval timeout = { 3, 0 };
select(1, &set, NULL, NULL, &timeout);
if (FD_ISSET(0, &set))
    read(0, buf, 1024);

论坛徽章:
0
6 [报告]
发表于 2016-11-16 09:10 |只看该作者
见apue-10.14 : SA_INTERRUPT
只有带这个选项的信号,可强制“系统调用不自动重启动”。

read接受到alarm信号后(我也测试了SIGINT), 信号响应后,依然会再进行read,程序“阻塞”在read。

程序改为:

#include <stdio.h>
#include <signal.h>
#include <string.h>

static
void handler(int sig)
{
    printf("recv a sig=%d\n",sig);
}

int main()
{
    char buf[1024];
    int ret;
    struct sigaction a;

    signal(SIGALRM, handler);

    memset(&a, 0, sizeof(a));
    a.sa_flags = SA_INTERRUPT;
    a.sa_handler = handler;
   
    sigaction(SIGINT, &a, NULL);
    alarm(3);
   
    ret = read(0, buf, sizeof(buf));
    if (ret == -1)
        printf("interrupt by alarm signal\n");
    return 0;
}

这样很明确可以测试:  alarm将“阻塞”在read,而CTRL+C将导致退出。
本程序在ubuntu14.04 x86_64测试通过。


论坛徽章:
0
7 [报告]
发表于 2016-11-16 09:10 |只看该作者
另外,感谢楼主给了大家一个“抠细节”的机会。

论坛徽章:
0
8 [报告]
发表于 2016-11-16 09:22 |只看该作者
刚才又看了看:
Linux中,以sigaction函数设置的信号处理,默认都是强制中断的,那个SA_INTERRUPT标识位应该是0,有这个符号是为了兼容性。
要“调用重启动”,须加SA_RESTART标志。

论坛徽章:
208
巨蟹座
日期:2013-09-02 09:16:36卯兔
日期:2013-09-02 20:53:59酉鸡
日期:2013-09-05 21:21:45戌狗
日期:2013-10-15 20:51:17寅虎
日期:2013-10-18 21:13:16白羊座
日期:2013-10-23 21:15:19午马
日期:2013-10-25 21:22:48技术图书徽章
日期:2013-11-01 09:11:32双鱼座
日期:2013-11-01 20:29:44丑牛
日期:2013-11-01 20:40:00卯兔
日期:2013-11-11 09:21:32酉鸡
日期:2013-12-04 19:56:39
9 [报告]
发表于 2016-11-16 09:33 |只看该作者
netdoger 发表于 2016-07-11 11:22
我想让read函数在没有输入的情况下,3秒后被时钟中断,请问该怎么做?(我的程序read不会被中断,
只是到了 ...

1. async read+select()
2. terminator rules

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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP