linux变长数组,变长数组在Linux USB当中的应用

本文介绍Linux USB子系统中urb结构体的巧妙设计。通过变长数据技术,在分配urb时预留额外内存,用于存储不同长度的数据。特别关注了usb_alloc_urb函数如何实现这一特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

偶然浏览Linux-USB的代码,发现了变长数据的妙用,总结一下,学起来。

所示的函数中

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;

}

usb_init_urb(urb);

return urb;

}

其中,

kmalloc分配新的urb时,多分配了一下内存,用于存储数据。

iso_packets * sizeof(struct usb_iso_packet_descriptor)

再来看urb结构体定义,结构体的末尾有个零数组,可以再分配urb的同时,在urb后的连续内存上,非配不等长的内存用来存储数据。

struct urb {

/* private: usb core and host controller only fields in the urb */

struct kref kref;/* reference count of the URB */

void *hcpriv;/* private data for host controller */

atomic_t use_count;/* concurrent submissions counter */

atomic_t reject;/* submissions will fail */

int unlinked;/* unlink error code */

/* public: documented fields in the urb that can be used by drivers */

struct list_head urb_list;/* list head for use by the urb's

* current owner */

struct list_head anchor_list;/* the URB may be anchored */

struct usb_anchor *anchor;

struct usb_device *dev;/* (in) pointer to associated device */

struct usb_host_endpoint *ep;/* (internal) pointer to endpoint */

unsigned int pipe;/* (in) pipe information */

unsigned int stream_id;/* (in) stream ID */

int status;/* (return) non-ISO status */

unsigned int transfer_flags;/* (in) URB_SHORT_NOT_OK | ...*/

void *transfer_buffer;/* (in) associated data buffer */

dma_addr_t transfer_dma;/* (in) dma addr for transfer_buffer */

struct scatterlist *sg;/* (in) scatter gather buffer list */

int num_mapped_sgs;/* (internal) mapped sg entries */

int num_sgs;/* (in) number of entries in the sg list */

u32 transfer_buffer_length;/* (in) data buffer length */

u32 actual_length;/* (return) actual transfer length */

unsigned char *setup_packet;/* (in) setup packet (control only) */

dma_addr_t setup_dma;/* (in) dma addr for setup_packet */

int start_frame;/* (modify) start frame (ISO) */

int number_of_packets;/* (in) number of ISO packets */

int interval;/* (modify) transfer interval

* (INT/ISO) */

int error_count;/* (return) number of ISO errors */

void *context;/* (in) context for completion */

usb_complete_t complete;/* (in) completion routine */

struct usb_iso_packet_descriptor iso_frame_desc[0];

/* (in) ISO ONLY */

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值