urb传输过程
![这里写图片描述](https://img-blog.csdn.net/20160309212745958)
/**
这个函数做了一下事情:
1 : 分配了内存空间,并清空
2 : 引用计数被置1,有一个不明白的地方是 : 这里的urb->anchor_list链表是干什么用的?
他在何时被添加节点,又是何时被移除节点的?
iso_packets : 这个urb中的等时数据包的数量
仅仅用于等时传输中。如果用于其他类型的传输,那么这个参数为0
mem_flags : 分配内存的标志,和kmalloc的标志一样,因为他底层就是用kmalloc来分配的
*/
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
{
struct urb *urb;
urb = kmalloc(sizeof(struct urb) +
iso_packets * sizeof(struct usb_iso_packet_descriptor),
mem_flags);
if (!urb) {
printk(KERN_ERR "alloc_urb: kmalloc failed\n");
return NULL;
/**
看他的使用 :
acecad->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!acecad->irq)
{
err = -ENOMEM;
goto fail2;
}
*/
}
/**
初始化urb,也就是 清空内存、引用计数置1等操作
那么,urb的引用计数有什么作用呢?
1 :
urb提交到usb主机控制器的时候,他的值被增加1
urb从主机控制器返回USB驱动程序的时候,他的值减少1
2 :
在下面的usb_free_urb()中也是依据urb的引用计数来释放urb的。
下面会有实验验证。请往下看。
*/
usb_init_urb(urb);
return urb;
}
/**
释放urb,
这个函数:
判断urb的引用计数,
如果为1的时候,就调用urb_destroy()来释放。
*/
void usb_free_urb(struct urb *urb)
{
if (urb)
{
kref_put(&urb->kref, urb_destroy);
}
}
static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{
return kref_sub(kref, 1, release);
}
/**
看他是调用 urb_destroy()函数来释放的。
*/
static inline int kref_sub(struct kref *kref, unsigned int count,void (*release)(struct kref *kref))
{
WARN_ON(release == NULL);
/**
atomic_sub_and_test :从原子类型的变量count中减去1,并判断结果是否为0,如果为0,返回真,否则返回假
当urb的引用计数为1的时候,会被释放
前面的usb_alloc_urb()将他置为 1的。
*/
if (atomic_sub_and_test((int) count, &kref->refcount))
{
/**
调用urb_destroy()来释放
*/
release(kref);
return 1;
}
return 0;
}
static void urb_destroy(struct kref *kref)
{
struct urb *urb = to_urb(kref);
if (urb->transfer_flags & URB_FREE_BUFFER)
{
/**
释放缓冲区
*/
kfree(urb->transfer_buffer);
}
/**
释放urb
*/
kfree(urb);
}
![这里写图片描述](https://img-blog.csdn.net/20160309221351446)