深入理解RDMA和socket-----比较RDMA和socket编程异同
1.简介 作者简介:翟文杰,百度人百度魂深入理解SOCKET三板斧recv,send,epoll。浅浅理解RDMA三板斧ibv_post_send,ibv_post_recv,ibv_poll_cq。 TODO: 内核中的nvme_tcp_data_ready(网卡将数据直接DMA至傲腾内存?),source code:https://elixir.bootlin.com/linux/latest/source/drivers/nvme/host/tcp.c#L1498 ep_poll_callback如何找到相关联的epitem并插入到rdlist中的。 RDMA内存注册时,mlock如何锁住物理页不被换出。 cqe如何完成回调。source code :https://elixir.bootlin.com/linux/latest/source/include/rdma/ib_verbs.h#L1349 巨人肩膀:https://zhuanlan.zhihu.com/p/164908617ref:linux5.12.9RDMA Aware Networks Programming User Manual Rev 1.7 linux源码快速跳转https://elixir.bootlin.com/linux/latest/source 2.SOCKET编程 2.1 SOCK 2.1.1 SOCK中的wait_queue 如下代码所示sk_wq是sock中实现异步回调的重要结构。sk_wq中含wait_queue,用于实现回调。 struct sock{ .... union { struct socket_wq __rcu *sk_wq; /* private: */ struct socket_wq *sk_wq_raw; /* public: */ }; ... } 在wait_queue其存放的数据实体如下代码所示。 struct wait_queue_entry { unsigned int flags; void *private; wait_queue_func_t func; struct list_head entry; }; private:推测为task_struct结构func 人如其名,是一个函数其余两个,后续分析没有用到,所以暂未知。 2.1.2 SOCK双子星 sock中有接收队列和发送队列,其类型为sk_buff。 struct sock{ .... struct sk_buff_head sk_receive_queue; struct sk_buff_head sk_write_queue; .... } sk_buff_head封装sk_buff链表头,含lock保证互斥访问,其中qlen表示链表中元素。 struct sk_buff_head { /* These two members must be first. */ struct sk_buff *next; struct sk_buff *prev; __u32 qlen; spinlock_t lock; }; sk_buff为索引结构,四个指针(tail,end,head,data)指向实际存储地址。 struct sk_buff{ ... sk_buff_data_t tail; sk_buff_data_t end; unsigned char *head, *data; ... } sk_buff由alloc_skb装配,该函数首先尝试在内核cache上分配sk_buff,不行就换到内核上。分配器是在numa架构上分配,为了支持numa进行了多层封装(具体如何在numa上分配,未知),最后跳到do_kmalloc,分配内核地址空间。 struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, int flags, int node) { struct kmem_cache *cache; struct sk_buff *skb; u8 *data; bool pfmemalloc; cache = (flags & SKB_ALLOC_FCLONE) ? skbuff_fclone_cache : skbuff_head_cache; /* Get the HEAD */ if ((flags & (SKB_ALLOC_FCLONE | SKB_ALLOC_NAPI)) == SKB_ALLOC_NAPI && likely(node == NUMA_NO_NODE || node == numa_mem_i