1.创建一个socket的内核结构图
如图:
创建一个socket,在内核中会创建如下几个选项:
a.创建接受队列sk_receive_queue,用于接受软中断时存储对应的数据信息.
b.等待队列sk_wq,当连接完成后,如果当前没有数据到来,那么当前进程会阻塞,并且状态从运行态切换至阻塞,并将当前进程关联的socket存储在该队列中,等到有数据到来的时候,内核在通过从该队列中获取对应的进程将其唤醒。
c.软中断处理函数sk_data_ready,会直接将软中断的回调函数注册好,当数据到来时候,调用该方法来进行处理。
d.协议族函数 proto_ops,内核中会将一些列的内核协议栈相关的处理函数提前注册,针对AF_INET对应的是inet_create;
e.初始化sock结构内部的相关队列信息.
2.等待数据到来
网卡收到数据是,sokcet对应内核流程图
上图流程图解:
a.用户进程通过调用recv函数,底层调用的还是recvfrom函数,进入内核中,通过tcp_recvmsg调用检查当前的socket的接收队列中是否有数据到来,如果没有数据到来,则将当前进程current关联socket并存储到等待队列中。并将当前进程状态从运行状态切换至阻塞状态,让出cpu交由其他进程使用。
b.当网卡收到数据时,触发一个硬中断,将数据从网卡通过DMA拷贝到内存RingBuff中,之后通过cpu触发一个软中断调用相关的数据接收处理函数tcp_queue_rcv.
c.通过处理函数tcp_queue_rcv将数据从内存存储到接收队列中。之后内核线程ksoftirq,通过调用sock_def_readable回调函数去当前的socket等待队列中,找到阻塞的进程,并将其唤醒冲新放置在运行队列继续运行处理数据。