本文共 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
#includestruct 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/