关于vb.netifin的信息

内核什么函数接收netif

背景:

10年积累的网站建设、做网站经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站设计后付款的网站建设流程,更有潞州免费网站建设让你可以放心的选择与我们合作。

内核接收分组的方式有两种:第一种:传统方式,使用中断的方式;第二种:NAPI,使用中断和轮询结合的方式。

中断方式:

下图为一个分组到达NIC之后,该分组穿过内核到达网络层函数的路径。

此图的下半部分为中断处理,上半部分为软中断。在中断处理中,函数net_interupt是

设备驱动程序的中断处理程序,它将确认此中断是否由接收到分组引发的,如果确实如此,

则控制权移交到函数net_rx。函数net_rx也是特定于NIC,首先创建一个新的套接字缓冲区,

分组的内容接下来从NIC传输到缓冲区(进入到物理内存中),然后使用内核源码中针对

各个传输类型的库函数来分析首部的数据。函数netif_rx函数不是特定于网络驱动函数,该

函数位于net/core/dev.c,调用该函数,标志着控制由特定于网卡的代码转移到了网络层的

通用接口部分。此函数的作用在于,将接收分组放置到一个特定于CPU的等待队列上,并

退出中断上下文。内核使用softnet_data来管理进出流量,其定义入下:

2352 /*

2353 * Incoming packets are placed on per-cpu queues

2354 */

2355 struct softnet_data {

2356 struct list_head poll_list;

2357 struct sk_buff_head process_queue;

2358

2359 /* stats */

2360 unsigned int processed;

2361 unsigned int time_squeeze;

2362 unsigned int cpu_collision;

2363 unsigned int received_rps;

2364 #ifdef CONFIG_RPS

2365 struct softnet_data *rps_ipi_list;

2366 #endif

2367 #ifdef CONFIG_NET_FLOW_LIMIT

2368 struct sd_flow_limit __rcu *flow_limit;

2369 #endif

2370 struct Qdisc *output_queue;

2371 struct Qdisc **output_queue_tailp;

2372 struct sk_buff *completion_queue;

2373

2374 #ifdef CONFIG_RPS

2375 /* Elements below can be accessed between CPUs for RPS */

2376 struct call_single_data csd ____cacheline_aligned_in_smp;

2377 struct softnet_data *rps_ipi_next;

2378 unsigned int cpu;

2379 unsigned int input_queue_head;

2380 unsigned int input_queue_tail;

2381 #endif

2382 unsigned int dropped;

2383 struct sk_buff_head input_pkt_queue; //对所有进入分组建立一个链表。

2384 struct napi_struct backlog;

2385

2386 };

第2383行的input_pkt_queue即是CPU的等待队列。netif_rx的实现如下:

3329 static int netif_rx_internal(struct sk_buff *skb)

3330 {

3331 int ret;

3332

3333 net_timestamp_check(netdev_tstamp_prequeue, skb);

3334

3335 trace_netif_rx(skb);

3336 #ifdef CONFIG_RPS //RPS 和 RFS 相关代码

3337 if (static_key_false(rps_needed)) {

3338 struct rps_dev_flow voidflow, *rflow = voidflow;

3339 int cpu;

3340

3341 preempt_disable();

3342 rcu_read_lock();

3343

3344 cpu = get_rps_cpu(skb-dev, skb, rflow); //选择合适的CPU id

3345 if (cpu 0)

3346 cpu = smp_processor_id();

3347

3348 ret = enqueue_to_backlog(skb, cpu, rflow-last_qtail);

3349

3350 rcu_read_unlock();

3351 preempt_enable();

3352 } else

3353 #endif

3354 {

3355 unsigned int qtail;

3356 ret = enqueue_to_backlog(skb, get_cpu(), qtail); //将skb入队

3357 put_cpu();

3358 }

3359 return ret;

3360 }

3361

3362 /**

3363 * netif_rx - post buffer to the network code

3364 * @skb: buffer to post

3365 *

3366 * This function receives a packet from a device driver and queues it for

3367 * the upper (protocol) levels to process. It always succeeds. The buffer

3368 * may be dropped during processing for congestion control or by the

3369 * protocol layers.

3370 *

3371 * return values:

3372 * NET_RX_SUCCESS (no congestion)

3373 * NET_RX_DROP (packet was dropped)

3374 *

3375 */

3376

3377 int netif_rx(struct sk_buff *skb)

3378 {

3379 trace_netif_rx_entry(skb);

3380

3381 return netif_rx_internal(skb);

3382 }

入队函数 enqueue_to_backlog的实现如下:

View Code

NAPI

NAPI是混合了中断和轮询机制,当一个新的分组到达,而前一个分组依然在处理,这时内核

并不需要产生中断,内核会继续处理并在处理完毕后将中断开启。这样内核就利用了中断和轮询的好处,

只有有分组到达的时候,才会进行轮询。

NAPI存在两个优势

1.减少了CPU使用率,因为更少的中断。

2.处理各种设备更加公平

只有设备满足如下两个条件时,才能实现NAPI:

1.设备必须能够保留多个接收的分组

2.设备必须能够禁用用于分组接收的IRQ。而且,发送分组或其他可能通过IRQ进行的操作,都仍然

必须是启用的。

其运行概览如下:

如上所示,各个设备在进入poll list前需要禁用IRQ,而设备中的分组都处理完毕后重新开启IRQ。poll list使用

napi_struct来管理设备,其定义如下:

View Code

变量state可以为NAPI_STATE_SCHED或NAPI_STATE_DISABLE, 前者表示设备将在

内核的下一次循环时被轮询,后者表示轮询已经结束且没有更多的分组等待处理,但

设备并没有从poll list移除。

支持NAPI的NIC需要修改中断处理程序,将此设备放置在poll list上。示例代码如下:

View Code

函数__napi_schedule的定义入下:

View Code

设备除了对中断处理进行修改,还需要提供一个poll函数,使用此函数从NIC中获取分组。示例代码如下:

特定于硬件的方法 hyper_do_poll 从NIC中获取分组,返回值work_done为处理的分组数目。当分组处理完后,

会调用netif_rx_complete将此设备从poll list中移除。ixgbe网卡的poll函数为ixgbe_poll, 而对于非NAPI的函数,

内核提供默认的处理函数process_backlog。

软中断处理相关

无论是NAPI接口还是非NAPI最后都是使用 net_rx_action 作为软中断处理函数。因此整个流程如下:

上图中有些函数名已经发生变更,但是流程依然如此。在最新的3.19内核代码中,非NAPI的调用流程如下:

neif_rx会调用enqueue_to_backlog 将skb存入softnet_data,并调用____napi_schedule函数。

netif_rx===netif_rx_internal===enqueue_to_backlog===____napi_schedule===net_rx_action===process_backlog===__netif_receive_skb

e100网卡的NAPI调用流程入下:

e100_intr===__napi_schedule===net_rx_action===e100_poll===e100_rx_clean===e100_rx_indicate===netif_receive_skb

asp.net时间判断的问题

System.DateTime currentTime=new System.DateTime();

string str="";

int h=currentTime.Hour;

if(h12)

{

str="下午";

}

else

{

str="上午";

}

1、DateTime 数字型

System.DateTime currentTime=new System.DateTime();

1.1 取当前年月日时分秒

currentTime=System.DateTime.Now;

1.2 取当前年

int 年=currentTime.Year;

1.3 取当前月

int 月=currentTime.Month;

1.4 取当前日

int 日=currentTime.Day;

1.5 取当前时

int 时=currentTime.Hour;

1.6 取当前分

int 分=currentTime.Minute;

1.7 取当前秒

int 秒=currentTime.Second;

1.8 取当前毫秒

int 毫秒=currentTime.Millisecond;

(变量可用中文)

1.9 取中文日期显示——年月日时分

string strY=currentTime.ToString("f"); //不显示秒

1.10 取中文日期显示_年月

string strYM=currentTime.ToString("y");

1.11 取中文日期显示_月日

string strMD=currentTime.ToString("m");

1.12 取中文年月日

string strYMD=currentTime.ToString("D");

1.13 取当前时分,格式为:14:24

string strT=currentTime.ToString("t");

1.14 取当前时间,格式为:2003-09-23T14:46:48

string strT=currentTime.ToString("s");

1.15 取当前时间,格式为:2003-09-23 14:48:30Z

string strT=currentTime.ToString("u");

1.16 取当前时间,格式为:2003-09-23 14:48

string strT=currentTime.ToString("g");

1.17 取当前时间,格式为:Tue, 23 Sep 2003 14:52:40 GMT

string strT=currentTime.ToString("r");

1.18获得当前时间 n 天后的日期时间

DateTime newDay = DateTime.Now.AddDays(100);


新闻标题:关于vb.netifin的信息
分享路径:http://ybzwz.com/article/dsieddg.html