信号可重入线程安全

信号可重入线程安全
2009-08-28 16:54
之所以把这几个概念放一起,是因为它们组合在一起容易出现一些莫名其妙的错误,而且一旦出现,还很难被发现。更糟糕的是它们的出现需要一定的时间,并不是非常容易重现的,而且需要了解的比较多才能更好的理解它们发生的原因。
这里要用例子阐述一下。

信号的是UNIX系统上是最原始的进程间通信方式之一(参考<<UNIX环境高级编程>>以及<<UNIX操作系统设计>>),信号本身不能携带任何的数据,只能通知别的进程表示某个事件,比如Ctrl-C通常只表示"我想中断你的执行"。
进程可以捕获除了,SIGSTOP,SIGKILL之外的任何信号,比如"当有人想中断我的执行请让我关闭我的文件".这两个信号保证进程在出问题的时候是可以控制的(不然它就是不退出,咋办?),如果信号被捕获,那么执行的那个地方就被暂时中断了,直到信号处理函数返回,才接着刚才被中断的地方执行;

可重入的概念就是一段代码可以被中断执行,然后又有一个新的执行流在执行它。可重入函数不能拥有公共资源。

信号可以由进程发送,也可以由内核发送,但是这里和是谁发送的无关,所以给的例子如下:





#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
void gotsig(int n)
{
    printf("haha");
}

int main()
{
    struct itimerval value;
        struct sigaction sact;

    sigemptyset( &sact.sa_mask );
     sact.sa_flags = 0;
     sact.sa_handler = gotsig;
    sigaction(SIGALRM,&sact,NULL);

     value.it_interval.tv_sec = 0;
     value.it_interval.tv_usec = 100000;
     value.it_value.tv_sec = 0;
     value.it_value.tv_usec = 1000;

    setitimer(ITIMER_REAL, &value,NULL);


    while(1) {
        /* other code here */
        printf("HA~");
    }
}



这个代码的意思就是每一毫秒发送给自己一次SIGALRM信号,然后一直打印
这个代码有什么问题,咋一看,看不出来有什么问题吧(如果你一眼就看出问题来,那么不要再往下阅读了^^)
答案是,很可能会死锁,死锁有几个必要条件,我要得到资源a的时候被阻塞,而能释放a的那个家伙又在等待我已经拥有的资源。
那么这里资源在哪呢,在printf的锁里,是什么东西,我咋不知道呢??

众所周知,操作系统支持多线程,而且标准IO是有缓冲的,显然stdout是全局资源(文件是属于进程的资源,是所有线程共享的,就像地址空间一样). 那么多线程printf的时候会发生什么?很显然,缓冲区的概念(消费者和生产者的故事应该知道)出来了,必须得有锁,否则缓冲区可能会出问题的(一个打印aaa,一个打印bbb,最后有可能打印aabbba)
这样的锁如果有,就表明printf是线程安全的,否则就不是线程安全的!

显然如果标准库的printf一族如果不是线程安全的,那么线程中就得自己加锁了,多麻烦的事情(虽然C标准没有线程的概念,但是我的标准库是线程安全的);

这样printf的行为大概为
int printf(const char *fmt,...)
{
    /**/
    加锁
tag1:
    操作缓冲,如果必要write(1,buf,size);
    释放锁
    /**/
}
这个锁肯定是所有线程可见的,这个函数不可重入,在信号处理中调用的时候,被中断的地方可能正是加锁和解锁之间的位置,这样信号处理中的printf进行同样的加锁解锁过程,因为那时候它已经拥有了锁(在被打断的时候),再去要锁,那么肯定得不到,信号处理中的printf永远阻塞在那锁的获取代码上,永远不会返回,信号处理函数也就永远不会返回,显然死锁了

strace ./a.out 会发现阻塞在futex上,这个系统调用正是我的系统上锁的实现所使用的(pthread_mutex_lock)
目前的死锁还只是这个线程,当别的线程调用printf时,也死锁了

总结一下
信号处理中不能调用不可重入函数,带有锁的函数是不可重入的
printf是线程安全的,同理,malloc也是,只是malloc操作地址空间,printf操作文件而已,都是全局资源,都有锁的

这只是个我遇到的情况,详细可以参考apue

http://hi.baidu.com/rdray/blog/item/753a53bef8f15d0319d81fba.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值