数组元素为0的说明

最近在看UVC摄像头驱动,发现了这几段代码:

for (j = 0; j < npackets; ++j) {
            urb->iso_frame_desc[j].offset = j * psize;//iso是实时的意思
            urb->iso_frame_desc[j].length = psize;

        }

跟踪iso_frame_desc  ,发现了0数组。

(在linux-3.4.20\include\linux\Usb.h里)

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 */
};

数组元素为0,表示struct usb_iso_packet_descriptor iso_frame_desc[0] 不占内存。那么内核代码这样写的意义是什么呢?

而且为何上面的UVC驱动代码urb->iso_frame_desc[j]里的数组元素不为0 ? ?

在结构体中,iso_frame_desc是一个数组名;但该数组没有元素;该数组的真实地址紧随结构体urb之后,而这个地址就是结构体后面数据的地址(如果给这个结构体分配的内容大于这个结构体实际大小,后面多余的部分就是这个iso_frame_desc的内容);这种声明方法可以巧妙的实现C语言里的数组扩展。


对于 urb->iso_frame_desc[j] 的使用,表明数组iso_frame_desc已经被分配了内存,那么在哪里分配的呢?

是通过 struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)  来分配的,数组iso_frame_desc的大小为iso_packets 。

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;
}



今天看linux中usb部分的代码,看到如下的数据结构:

struct   urb
{
    ......
    struct   iso_packet_descriptor   iso_frame_desc[0];
};
觉得很差异,0个元素的数组?
google了一下相关内容:

只有0个元素的数组在某些情况下是很有用处的,在WINDOWS的头文件里经常有这样的情况出现。例如:

typedef   struct   _TestStruct_
{
        int   nItemCount;
        ANY_TYPE   item[0];
}TEST_STRUCT;

此时,用sizeof(TEST_STRUCT)得到的数值为4,即sizeof(int),后面的在结构体ANY_TYPE里是不占空间的。如果我们要分配100个item,可以这样:
TEST_STRUCT   *   pTestStruct   =   (TEST_STRUCT   *)malloc(sizeof(TESTSTRUCT)   +   sizeof(ANT_TYPE)   *   100);

在要访问第n个item时,可以这样来访问   pTestStruct-> item[n],是不是很方便?



参考:https://bbs.csdn.net/topics/80291402

猜你喜欢

转载自blog.csdn.net/qq_26093511/article/details/80624198