通过上一篇分析,可以判断出do_monitor线程死锁的地方,并给出了两个临时解决办法:
1.如果发生死锁,将当前的事件抛弃掉,不予处理。
2.如果将要发生死锁,并且消息是CLF、CCL、RSC等事件,可以将chan的bridged进行hangup。等通道线程从write中返回后,会立即挂断当前通话的两个channel。
经过上午的测试,可以看出使用方法2有效的解决这个问题。
问题的根本解决应该还是要追查关于write的问题,这个需要对驱动中关于write的处理进行分析,作为下一步要做的事情之一吧。
另外一个话题-----关于MTP层的日志和抓包
在chan_ss7中对于MTP层的日志进行了特殊处理,不是简单使用ast_log的方式,而是通过receivedbuf进行中转了一把。先将log通过fifo_log的方式将日志作为一种特殊的事件提交到receivedbuf中,再在do_monitor线程中取出event,进行log记录。
在chan_ss7中也提供了MTP2层的数据抓包,并且可以在CLI里通过ss7 dump start 的形式进行开启抓包。抓包的处理过程与log类似,也是通过receivedbuf来完成的。
可以看出,在chan_ss7代码中,为了避免死锁问题,作者已经用了多种方式来规避这个问题,receivedbuf就是一个例子。关于receivedbuf是提供了一段缓冲区存放从mtp层接收到需要处理的event。这段缓冲区是在初始化的时候就分配好的,运行过程中不会动态增加,这就是作为一个典型的生产者-消费者的概念。receivedbuf就是一个盘子。event就是盘子里的食物。
receivedbuf是一个lffifo结构,看这个结构的定义:
struct lffifo {
int size;
int start;
int end;
unsigned char buf[0];
};
接收到的event会存放到buf中,start记录存储开始位置,end记录存储结束位置,size记录buf大小。在lffifo.c中提供了对buf的访问方式,封装的较好,功能包括put、get等。
阅读(2711) | 评论(0) | 转发(1) |