Linux数据报文接收发送总结5
生活随笔
收集整理的這篇文章主要介紹了
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** 0800 IP* 8100 802.1Q VLAN* 0001 802.3* 0002 AX.25* 0004 802.2* 8035 RARP* 0005 SNAP* 0805 X.25* 0806 ARP* 8137 IPX* 0009 Localtalk* 86DD IPv6*/ #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.c void 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); }?
?
?
總結
以上是生活随笔為你收集整理的Linux数据报文接收发送总结5的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 服务器扩充后问题总结:Value too
- 下一篇: Linux数据报文接收发送总结6