1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Linux数据报文接收发送总结5

Linux数据报文接收发送总结5

时间:2022-03-16 23:36:04

相关推荐

Linux数据报文接收发送总结5

2.2 网络子系统初始化

linux内核通过调用subsys_initcall来初始化各个子系统,在源代码目录里你可以grep出许多对这个函数的调用。这里我们要说的是网络子系统的初始化,会执行到net_dev_init函数。

/**Initialize the DEV module. At boot time this walks the device list and*unhooks any devices that fail to initialise (normally hardware not*present) and leaves us with a valid list of present and active devices.**//** This is called single threaded during boot, so no need* to take the rtnl semaphore.*/static int __init net_dev_init(void){int i, rc = -ENOMEM;BUG_ON(!dev_boot_phase);if (dev_proc_init())goto out;if (netdev_kobject_init())goto out;INIT_LIST_HEAD(&ptype_all);for (i = 0; i < PTYPE_HASH_SIZE; i++) // 初始化网络协议hash链表,如ip/ipv6/icmp/arp等协议,用于接收报文协议处理ptype_baseINIT_LIST_HEAD(&ptype_base[i]);INIT_LIST_HEAD(&offload_base);if (register_pernet_subsys(&netdev_net_ops))goto out;/**Initialise the packet receive queues.*/for_each_possible_cpu(i) {struct softnet_data *sd = &per_cpu(softnet_data, i);skb_queue_head_init(&sd->input_pkt_queue);skb_queue_head_init(&sd->process_queue);INIT_LIST_HEAD(&sd->poll_list);sd->output_queue_tailp = &sd->output_queue;#ifdef CONFIG_RPSsd->csd.func = rps_trigger_softirq;sd->csd.info = sd;sd->cpu = i;#endifsd->backlog.poll = process_backlog;sd->backlog.weight = weight_p;}dev_boot_phase = 0;/* The loopback device is special if any other network devices* is present in a network namespace the loopback device must* be present. Since we now dynamically allocate and free the* loopback device ensure this invariant is maintained by* keeping the loopback device as the first device on the* list of network devices. Ensuring the loopback devices* is the first device that appears and the last network device* that disappears.*/if (register_pernet_device(&loopback_net_ops))goto out;if (register_pernet_device(&default_device_ops))goto out;open_softirq(NET_TX_SOFTIRQ, net_tx_action);open_softirq(NET_RX_SOFTIRQ, net_rx_action);hotcpu_notifier(dev_cpu_callback, 0);dst_subsys_init();rc = 0;out:return rc;}subsys_initcall(net_dev_init);//file : linux/netdevice.h/**The list of packet types we will receive (as opposed to discard)*and the routines to invoke.**Why 16. Because with 16 the only overlap we get on a hash of the*low nibble of the protocol value is RARP/SNAP/X.25.**NOTE: That is no longer true with the addition of VLAN tags. Not* sure which should go first, but I bet it won't make much* difference if we are running VLANs. The good news is that* this protocol won't be in the list unless compiled in, so* the average user (w/out VLANs) will not be adversely affected.* --BLG**0800IP*8100 802.1Q VLAN*0001802.3*0002AX.25*0004802.2*8035RARP*0005SNAP*0805X.25*0806ARP*8137IPX*0009Localtalk*86DDIPv6*/#define PTYPE_HASH_SIZE(16)#define PTYPE_HASH_MASK(PTYPE_HASH_SIZE - 1)

在这个函数里,会为每个CPU都申请一个softnet_data数据结构,在这个数据结构里的poll_list是等待驱动程序将其poll函数注册进来,稍后网卡驱动初始化的时候我们可以看到这一过程。

另外open_softirq注册了每一种软中断都注册一个处理函数。NET_TX_SOFTIRQ的处理函数为net_tx_action,NET_RX_SOFTIRQ的为net_rx_action。继续跟踪open_softirq后发现这个注册的方式是记录在softirq_vec变量里的。后面ksoftirqd线程收到软中断的时候,也会使用这个变量来找到每一种软中断对应的处理函数。

//file: kernel/softirq.cvoid open_softirq(int nr, void (*action)(struct softirq_action *)){softirq_vec[nr].action = action;}static void run_ksoftirqd(unsigned int cpu){local_irq_disable();if (local_softirq_pending()) {/** We can safely run softirq on inline stack, as we are not deep* in the task stack here.*/__do_softirq();local_irq_enable();cond_resched_rcu_qs();return;}local_irq_enable();}asmlinkage __visible void __do_softirq(void){unsigned long end = jiffies + MAX_SOFTIRQ_TIME;unsigned long old_flags = current->flags;int max_restart = MAX_SOFTIRQ_RESTART;struct softirq_action *h;bool in_hardirq;__u32 pending;int softirq_bit;/** Mask out PF_MEMALLOC s current task context is borrowed for the* softirq. A softirq handled such as network RX might set PF_MEMALLOC* again if the socket is related to swap*/current->flags &= ~PF_MEMALLOC;pending = local_softirq_pending();account_irq_enter_time(current);__local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);in_hardirq = lockdep_softirq_start();restart:/* Reset the pending bitmask before enabling irqs */set_softirq_pending(0);local_irq_enable();h = softirq_vec; // 软件中断向量while ((softirq_bit = ffs(pending))) {unsigned int vec_nr;int prev_count;h += softirq_bit - 1;vec_nr = h - softirq_vec;#ifdef IP_SPEEDUP_DEBUGg_vec_nr[smp_processor_id()] = vec_nr;#endifprev_count = preempt_count();kstat_incr_softirqs_this_cpu(vec_nr);#ifdef CONFIG_RTK_HOST_SPEEDUPif (isHostSpeedUpEnable())send_delay_ack_timer();#endiftrace_softirq_entry(vec_nr);h->action(h); // 中断处理函数trace_softirq_exit(vec_nr);if (unlikely(prev_count != preempt_count())) {pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n",vec_nr, softirq_to_name[vec_nr], h->action,prev_count, preempt_count());preempt_count_set(prev_count);}h++;pending >>= softirq_bit;}rcu_bh_qs();local_irq_disable();pending = local_softirq_pending();#ifdef CONFIG_RTK_HOST_SPEEDUPif (isHostSpeedUpEnable()){int unAckSegment;unAckSegment = send_delay_ack_timer();if (unAckSegment){if (pending || time_before(jiffies, end))goto restart;//printk("unAck in softirq!\n");}}#endifif (pending) {if (time_before(jiffies, end) && !need_resched() &&--max_restart)goto restart;wakeup_softirqd();}lockdep_softirq_end(in_hardirq);account_irq_exit_time(current);__local_bh_enable(SOFTIRQ_OFFSET);WARN_ON_ONCE(in_interrupt());tsk_restore_flags(current, old_flags, PF_MEMALLOC);}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。