2009年2月19日星期四

高速数据交换时的lock问题

作者:Sam(甄峰) sam_code@hotmail.com

Sam在作Bluetooth Remote Control程序时,遇到一个问题。
手柄每5ms发送一个数据包。
而Sam程序是这样设计的:
在手柄连接时,BTRC创建Read thread. 在Read thread中会读取手柄数据并解析包。解析结果放到一个buffer(结构体)中。
另外一边,应用程序会使用BTRC的read接口去读取这个buffer的内容。这个应用程序应该会用一个thread去不断的调用BTRC的read接口去读取。


方案一:
Sam在解析包部分向buffer中写东西时会加锁,写完会解锁。BTRC的read接口读取buffer时加锁,读完会解锁。
但这样有个后果:
1. 如果 双方都是全速运行,也就是说:如果双方都不添加sleep.则会出现:程序先进入BTRC的read接口读取buffer很多次(20次)左右。这个时候,BTRC的使用BTX去读取并解析然后写入buffer的程序的lock无法进入。
然后,在某一时刻,BTRC使用BTX区读取并解析然后写入buffer的程序又集中运行很多次(15-20次)。
这就造成上层程序使用BTRC的读取接口读到的解析后的数据完全不正确。

2. 如果上层程序调用BTRC的读取接口时作一个延迟,比如4ms.
这样的话,因为程序使用BTRC 的读取接口有一个延迟,所以BTRC是用BTX去读取并解析然后写入buffer的程序有更大机会去写入。但会造成写入多个才能够读取一次的情况。例如:A包过来了,BTRC使用BTX去读取,解析后写入buffer. A+1包又过来了,然后BTRC使用BTX读取时,BTRC的读接口来读buffer,但buffer已经被lock了。所以只能等下一次去读取了。这造成只能读取第二个包。所以还是会造成丢包。

3. 如果去掉lock,并全速运行:
现象与情况一相同。


方案二:
将BTRC的读接口改造,每次不是再去读当前的一份数据,而是如下去做:
用返回值表示从上次读取到此次读取这段时间内,buffer中新的数据包个数。参数为指针的指针。指向数据头。





注[1]:Sam有个感觉,在不同速度的CPU上,尤其是一些嵌入式平台中,thread的schedule速度好像比较慢,所以在不同thread之前的切换速度比较慢。像在X5平台上,BTRC的Read接口去read buffer, 竟然只能读到30%-40%的包。Canmore可以读到70%的包。而PC上则可以读到100%的包,还有重复读到的。





没有评论: