我正在制作用于使用C语言控制各种嵌入式设备的小型库。我正在使用UDP套接字与每个设备进行通信。设备向我发送各种有趣的数据,警报和通知,同时它们发送一些由库内部使用的数据,但可能对用户不感兴趣。所以,我实现了一种回调方法,用户可以在每个设备上注册回调函数和一些有趣的事件。现在,这个库的整体设计是这样的: -
while
事件循环,它使用select
和non-blocking sockets
来维护与每个设备的通信。DEVICE_ID
,REQUES_TIME
的标题(时间请求为发送以检索该数据包和RETRIEVAL_TIME
(数据包实际到达的时间)和REQUEST_ID
以及REQUEST_TYPE
(警报,数据,通知等)。基本上,我在主题2中做了类似的事情: -
THREAD#2
wait(data_put_in_buffer_cond)
lock(buffer_mutex)
packet_t* packet = pop_packet_from_buffer(buf);
unlock(buffer_mutex)
/* parsing the package... */
parsed_packet_t* parsed_packet = parse_and_change_endianess(packet->data);
/* header for put by thread #1 with host byte order only not parsing necessary */
header_t* header = get_header(packet);
/* thread 1 sets free callback for kind of packet it puts in buffer
* This not a critical section section of buffer, so fine without locks
*/
buffer.free_callback(packet);
foreach attribute in parsed_packet->attribute_list {
register_info_t* rinfo = USER_REGISTRED_EVENT_TABLE[header->device_id][attribute.attr_id];
/*user is register with this attribute ID on this device ID */
if(rinfo != NULL) {
rinof->callback(packet);
}
// Do some other stuff with this attribute..
}
free(parsed_packet);
现在,我担心的是,如果用户实现的回调函数需要一些时间才能完成,同时由于环形缓冲区处于覆盖模式,我可能会丢弃一些数据包会发生什么?我已经测试了我的3到4个设备的API,如果回调函数等待合适的时间,我看不到很多丢弃事件。我猜测这种方法可能不是最好的。
如果我使用某种线程池来运行用户回调函数,它会是一个更好的设计吗?在那种情况下,我需要在将数据包发送给用户回调之前制作显式的数据包副本?每个数据包大约有500到700个字节,每个设备每秒大约可以获得2个数据包。任何有关改进当前设计或解决此问题的建议或意见将不胜感激。
答案 0 :(得分:1)
每台设备获得500-700字节根本不是问题,特别是如果您只有3-4台设备。即使你有100个设备,也不应该是一个问题。复制开销很可能是微不足道的。所以,我的建议是:在你确定缓冲区复制是你的瓶颈之前,不要先尝试优化。
关于丢失数据包,正如您在问题中所说,您已经在使用缓冲环(我假设它类似于循环队列,对吧?)。如果队列已满,那么您只需要使线程#1等待,直到队列中有可用空间为止。显然,来自不同设备的更多事件可能会到来,但这应该不是问题。一旦您再次拥有空间,select
将告知您有来自不同设备的可用数据,因此您只需要处理所有数据。当然,为了拥有一个平衡的系统,您可以将队列的大小设置为尽可能减少队列已满的次数的值,因此,线程#1需要等待。