博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
libusb源码学习:list_entry
阅读量:4181 次
发布时间:2019-05-26

本文共 3316 字,大约阅读时间需要 11 分钟。

USB开发涉及到libusb,看了下源码,现在已经到了1.0.23版;全部用的C,编译器和平台的普适性相对比较强;

其中的list_head作为关键链表,也是各个链接结构的成员(member)变量。而利用这个成员变量完成各个结构链接,涉及到几个很有意思的宏,其中包括list_entry,list_for_each_entry,这种用法和我们最普通的用法有点区别:在C ++中,通常我用标准std::list, std::vector实现;在C中,我们往往直接使用结构自自身的指针来完成链接,而不是使用这种成员链接指针(list_head)。

写了个list_entry应用原理的解析,用3种完全等价的方式找到:dev->session_data == 2

#include 
struct list_head { struct list_head* prev, * next;};/* Get an entry from the list * ptr - the address of this list_head element in "type" * type - the data type that contains "member" * member - the list_head element in "type" */#define list_entry(ptr, type, member) \ ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))#define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) /* Get each entry from a list * pos - A structure pointer has a "member" element * head - list head * member - the list_head element in "pos" * type - the type of the first parameter */#define list_for_each_entry(pos, head, member, type) \ for (pos = list_entry((head)->next, type, member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, type, member))#define list_for_each_entry_safe(pos, n, head, member, type) \ for (pos = list_entry((head)->next, type, member), \ n = list_entry(pos->member.next, type, member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, type, member))#define list_empty(entry) ((entry)->next == (entry))struct libusb_device { int refcnt; uint8_t bus_number; uint8_t port_number; struct libusb_device* parent_dev; uint8_t device_address; uint8_t num_configurations; struct list_head list; unsigned long session_data; };libusb_device* list_entry_func(list_head* ptr) { uintptr_t upt = offsetof(libusb_device, list); upt = (uintptr_t)(ptr) - upt; return (libusb_device*)(upt);}int main() { libusb_device ld1; libusb_device ld2; libusb_device ld3; ld1.list.next = &ld2.list; ld2.list.prev = &ld1.list; ld2.list.next = &ld3.list; ld3.list.prev = &ld2.list; ld1.session_data = 1; ld2.session_data = 2; ld3.session_data = 3; struct list_head usb_devs; usb_devs.next = &ld1.list; usb_devs.prev = &ld3.list; struct libusb_device* dev; struct libusb_device* ret = NULL; //#define list_entry(ptr, type, member) \ //((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))//#define list_first_entry(ptr, type, member) \ //list_entry((ptr)->next, type, member)//#define list_for_each_entry(pos, head, member, type) \ //for (pos = list_entry((head)->next, type, member); \ // &pos->member != (head); \ // pos = list_entry(pos->member.next, type, member)) list_for_each_entry(dev, &usb_devs, list, struct libusb_device) if (dev->session_data == 2) { std::cout << "found the member in the list: 0 !" << std::endl; break; } for (dev = list_entry_func(usb_devs.next); &dev->list != &usb_devs; dev = list_entry_func(dev->list.next)) { if (dev->session_data == 2) { std::cout << "found the member in the list: 1 !" << std::endl; break; } }; for (dev = list_entry(usb_devs.next, libusb_device, list); &dev->list != &usb_devs; dev = list_entry(dev->list.next, libusb_device, list)) if (dev->session_data == 2) { std::cout << "found the member in the list: 2 !" << std::endl; break; } return 0;}

 

转载地址:http://ipwoi.baihongyu.com/

你可能感兴趣的文章
一道面试题深入了解java底层
查看>>
java下载附件
查看>>
cron表达式每个月最后一天
查看>>
Oracle中Like与Instr模糊查询性能大比拼
查看>>
Spring Boot入门===Hello World
查看>>
spring boot应用启动原理分析
查看>>
使用spring的好处
查看>>
微服务:分解应用以实现可部署性和可扩展性
查看>>
tcp_timestamps tcp_tw_recycle引起的服务器连接不上问题
查看>>
windows下ES和head插件的安装
查看>>
RAP一种更高效的前后端接口对接解决方案
查看>>
ELK(ElasticSearch, Logstash, Kibana)搭建实时日志分析平台
查看>>
ELK搭建教程(全过程)
查看>>
maven私服搭建使用
查看>>
Netty学习路线总结
查看>>
基于mybatis拦截器实现数据权限
查看>>
分布式文件系统FastDFS详解
查看>>
centos7上rabbitmq搭建
查看>>
rabbitmq集成spring的xml配置和java代码
查看>>
RabbitMQ消息确认(发送确认,接收确认)
查看>>