<p>linux内核有很多优秀的代码...</p>
<p>比如list</p>
<p> </p>
<p>这是一个双向链表。</p>
<p>先贴个好文章...</p>
<p><a href="https://myao0730.blogspot.com/2016/12/linux.html">https://myao0730.blogspot.com/2016/12/linux.html</a></p>
<p> </p>
<hr>
<p>先看下list_head的结构体,</p>
<pre class="blockcode"><code class="language-cpp">/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
}; </code></pre>
<p>非常简单, 就记录了两个指针, 一个指向前面节点, 一个指向后面节点。</p>
<hr>
<p>以dwc3驱动为例, 看下list如何使用。</p>
<pre class="blockcode"><code class="language-cpp">static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total)
{
struct dwc3_ep *dep;
u8 epnum;
INIT_LIST_HEAD(&dwc->gadget.ep_list);</code></pre>
<p>初始化端点时, 初始化了一个list_head, 叫ep_list</p>
<p> </p>
<p>看下INIT_LIST_HEAD宏,</p>
<pre class="blockcode"><code class="language-cpp"> 25 static inline void INIT_LIST_HEAD(struct list_head *list)
26 {
27 list->next = list;
28 list->prev = list;
29 } </code></pre>
<p>即该list_head的prev, next指针都指向自己。</p>
<p>也就是说这个list目前是空的。</p>
<p> </p>
<p>端点初始化函数中, 继续往下翻,</p>
<pre class="blockcode"><code class="language-cpp"> if (num == 0) {
usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
dep->endpoint.maxburst = 1;
dep->endpoint.ops = &dwc3_gadget_ep0_ops;
if (!direction)
dwc->gadget.ep0 = &dep->endpoint;
} else if (direction) {
int mdwidth;
int kbytes;
int size;
int ret;
mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
/* MDWIDTH is represented in bits, we need it in bytes */
mdwidth /= 8;
size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num));
size = DWC3_GTXFIFOSIZ_TXFDEF(size);
/* FIFO Depth is in MDWDITH bytes. Multiply */
size *= mdwidth;
kbytes = size / 1024;
if (kbytes == 0)
kbytes = 1;
/*
* FIFO sizes account an extra MDWIDTH * (kbytes + 1) bytes for
* internal overhead. We don't really know how these are used,
* but documentation say it exists.
*/
size -= mdwidth * (kbytes + 1);
size /= kbytes;
usb_ep_set_maxpacket_limit(&dep->endpoint, size);
dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list,
&dwc->gadget.ep_list);
ret = dwc3_alloc_trb_pool(dep);
if (ret)
return ret;
} else {
int ret;
usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list,
&dwc->gadget.ep_list);
ret = dwc3_alloc_trb_pool(dep);
if (ret)
return ret;
}</code></pre>
<p>这里有些逻辑, |
|