2017-07-14 115 views
1
#define MEMBER_OFFSET(c_type, mbr_name) ((uint32_t) (uintptr_t)(&((c_type*)0)->mbr_name)) 
#define CACHE_ALIGN __attribute__((aligned(EF_VI_DMA_ALIGN))) 

struct pkt_buf { 
    struct pkt_buf* next; 
    ef_addr dma_buf_addr; 
    int id; 
    uint8_t dma_buf[1] CACHE_ALIGN; 
}; 


struct pkt_buf* pkt_bufs [N_BUFS]; 

for(i = 0; i < N_BUFS; ++i) { 
    struct pkt_buf* pb = (struct pkt_buf*) ((char*) p + i * 2048); 
    pb->id = i; 
    pb->dma_buf_addr = ef_memreg_dma_addr(&memreg, i * 2048); 
    pb->dma_buf_addr += MEMBER_OFFSET(struct pkt_buf, dma_buf); // why do this? 
    pkt_bufs[i] = pb; 
} 

问题>我理解MEMBER_OFFSET的含义。但是,我没有得到以下行的含义:向dma_buf_addr的地址添加偏移量的用法是什么?

pb->dma_buf_addr += MEMBER_OFFSET(struct pkt_buf, dma_buf) 

基本上,MEMBER_OFFSET(struct pkt_buf, dma_buf)值以字节为成员变量dma_bufstruct pkt_buf偏移值。

回答

0

此代码使用'struct hack'的变体,后来被'灵活的数组成员'取代。 memregp都没有在代码中定义,函数也没有(宏?)ef_memreg_dma_addr(),所以这里有推测的元素。

但是,做计算,使得如果

pb->dma_buf_addr = ef_memreg_dma_addr(&memreg, i * 2048); 

pb->dma_buf_addr点到struct pkt_buf的开始,那么在转让之后:

pb->dma_buf_addr += MEMBER_OFFSET(struct pkt_buf, dma_buf); 

pb->dma_buf_addr指向的地址包中的dma_buf数组。使用的i * 2048表明p是分割成2个KiB页面的连续内存块,并且DMA缓冲器紧接在ID字段之后。