网络设备初始化主要流程是?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络设备初始化主要流程是?相关的知识,希望对你有一定的参考价值。
网卡驱动初始化
网络设备驱动加载时,内核会调用一个驱动程序注册的初始化函数。 内核提供了一个宏 module_init 来执行注册操作。
igb 模块的初始化函数长这样(请叫我程序拷贝员)。
/**
* igb_init_module - Driver Registration Routine
*
* igb_init_module is the first routine called when the driver is
* loaded. All it does is register with the PCI subsystem.
**/
static int __init igb_init_module(void)
int ret;
pr_info("%s - version %s\\n",
igb_driver_string, igb_driver_version);
pr_info("%s\\n", igb_copyright);
#ifdef CONFIG_IGB_DCA
dca_register_notify(&dca_notifier);
#endif
ret = pci_register_driver(&igb_driver);
return ret;
module_init(igb_init_module);
可以看到主要是有个 pci_register_driver 的函数,下面看看它干了啥。
PCI初始化
网卡一般都是PCI设备,可以用命令lspci查看。 PCI设备通过配置空间中的一系列寄存器来识别自己。 驱动会使用内核提供的宏 MODULE_DEVICE_TABLE 来导出驱动支持的PCI设备(使用设备ID标识)。 内核会用这个表决定加载特定的驱动从而控制PCI设备。
static const struct pci_device_id igb_pci_tbl[] =
PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_1GBPS) ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII) ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_BACKPLANE_2_5GBPS) ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_I211_COPPER), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_COPPER), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_FIBER), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_I210_SERDES), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SGMII), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SERDES), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_BACKPLANE), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_DH89XXCC_SFP), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_NS_SERDES), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES_QUAD), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER_ET2), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 ,
PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER), board_82575 ,
/* required last entry */
0,
;
MODULE_DEVICE_TABLE(pci, igb_pci_tbl);
pci_register_driver 使用 igb_driver 作为参数。igb_driver 则使用 igb_pci_tbl 赋值给域 id_table。
static struct pci_driver igb_driver =
.name = igb_driver_name,
.id_table = igb_pci_tbl,
.probe = igb_probe,
.remove = igb_remove,
#ifdef CONFIG_PM
.driver.pm = &igb_pm_ops,
#endif
.shutdown = igb_shutdown,
.sriov_configure = igb_pci_sriov_configure,
.err_handler = &igb_err_handler
;
重头戏 igb_probe
igb_driver 有个很重要的域 igb_probe。内核识别到PCI设备驱动后,就会调用pci_driver 中 probe 指向的函数。对 igb 来说,就是 igb_probe 函数。
igb_probe 会执行以下操作:
启用PCI设备。
设置DMA掩码。
请求内存区域和IO端口。
注册ethtool函数。
分配 net_device,这个结构代表一个抽象的网络设备。
注册 net_device_ops 到 net_device 的 netdev_ops 域。
设置 net_device 的features。
还有一些杂七杂八的工作都在这里完成,watchdog, 缓冲区分配等等。
struct net_device_ops 包含网络子系统操作设备的诸多函数指针。
static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)...
netdev->netdev_ops = &igb_netdev_ops;
...
static const struct net_device_ops igb_netdev_ops =
.ndo_open = igb_open,
.ndo_stop = igb_close,
.ndo_start_xmit = igb_xmit_frame,
.ndo_get_stats64 = igb_get_stats64,
.ndo_set_rx_mode = igb_set_rx_mode,
.ndo_set_mac_address = igb_set_mac,
.ndo_change_mtu = igb_change_mtu,
.ndo_do_ioctl = igb_ioctl,
.ndo_tx_timeout = igb_tx_timeout,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid,
.ndo_set_vf_mac = igb_ndo_set_vf_mac,
.ndo_set_vf_vlan = igb_ndo_set_vf_vlan,
.ndo_set_vf_rate = igb_ndo_set_vf_bw,
.ndo_set_vf_spoofchk = igb_ndo_set_vf_spoofchk,
.ndo_get_vf_config = igb_ndo_get_vf_config,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = igb_netpoll,
#endif
.ndo_fix_features = igb_fix_features,
.ndo_set_features = igb_set_features,
.ndo_fdb_add = igb_ndo_fdb_add,
.ndo_features_check = igb_features_check,
1) 进行硬件上的准备工作,检查网络设备是否存在,如果存在,则检测设备所使用的硬件资源。
2) 进行软件接口上的准备工作,分配net_device结构体并对其数据和函数指针成员赋值。
3) 获得设备的私有信息指针并初始化各成员的值。如果私有信息中包括自旋锁或信号量等并发或同步机制,则需对其进行初始化。
对net device结构体成员及私有数据的赋值都可能需要与硬件初始化工作协同进行,即硬件检测出了相应的资源,需要根据检测结果填充net_device结构体成员和私有数据。
网络设备驱动的初始化函数模板,具体的设备驱动初始化函数并不一定完全和本模板一样,但其本质过程是一致的。
xxx_hw_init()函数完成的与硬件相关的初始化操作如下。
1) 探测xxx网络设备是否存在。探测的方法类似于数学上的“反证法”,即先假设存在设备xxx,访问该设备,如果设备的表现与预期一致,就确定设备存在;否则,假设错误,设备xxx不存在。
2) 探测设备的具体硬件配置。一些设备驱动编写得非常通用,对于同类的设备使用统一的驱动,我们需要在初始化时探测设备的具体型号。另外,即便是同一设备,在硬件上的配置也可能不一样,我们也可以探测设备所使用的硬件资源。
3) 申请设备所需要的硬件资源,如用request region ()函数进行IO端口的申请等,但是这个过程可以放在设备的打开函数xxx open()中完成。
linux操作系统启动流程和光盘镜像制作
1、简述linux操作系统启动流程
POST (加电自检):自检主要硬件设备如:CPU、内存、硬盘是否正常,以及输入输出设备是否存在问题等。
BIOS(Boot Sequence):BIOS(基本的输入输出系统)装载在硬件芯片CMOS之上,自检时会启动这个程序,并根据CMOS上的配置信息去读取其他的硬件信息,检测正常之后进行硬件设备的初始化。
读取MBR:引导加载程序,在MBR(主引导记录)中,主要功能是识别,加载系统的核心文件,并提交到内存中运行来启动对应的系统。
Kernel运行:Kernel会自身初始化,探测可识别的硬件设备,Kernel是存在硬盘之中的,但是在内核启动时还没有加载硬盘,为了解决这个问题Kernel内核通过ramdisk(虚拟文件系统)来加载硬件程序,为防止根文件系统加载时出现bug等问题无法挽回的情况,以只读方式来挂载根文件系统,来完成跟文件系统的初始化。
init运行:在内核、硬件及驱动信息加载完毕后,内核会运行用户空间的第一个应用程序:/sbin/init.包括系统的主机名、网络管理、文件系统格式等其他服务。
默认运行级别、系统初始化、关闭及启动服务、启动终端(图形终端):
运行级别:为了系统的运行或维护等目的而设定的机制;
0-6:7个级别;
0、关机, shutdown
1、单用户模式(single user),root用户,无须认证;维护模式;
2、多用户模式(multi user),会启动网络功能,但不会启动NFS;维护模式;
3、多用户模式(mutli user),完全功能模式;文本界面;
4、预留级别:目前无特别使用目的,但习惯以同3级别功能使用;
5、多用户模式(multi user), 完全功能模式,图形界面;
6、重启,reboot
默认级别:3, 5
级别切换:init #
级别查看:
who -r
runlevel
系统初始化脚本:/etc/rc.d/rc.sysinit
(1) 设置主机名;
(2) 设置欢迎信息;
(3) 激活udev和selinux;
(4) 挂载/etc/fstab文件中定义的所有文件系统;
(5) 检测根文件系统,并以读写方式重新挂载根文件系统;
(6) 设置系统时钟;
(7) 根据/etc/sysctl.conf文件来设置内核参数;
(8) 激活lvm及软raid设备;
(9) 激活swap设备;
(10) 加载额外设备的驱动程序;
(11) 清理操作;
系统初始化时运行的脚本在/etc/rc.d/rc.sysinit配置文件中;关闭及启动服务意味着启动或关闭/etc/rc.d/rc#.d/目录下的服务脚本所控制的服务,最后就是启动终端(图形终端)了
2、简述grub启动引导程序配置及命令行接口详解
grub的三个阶段:
stage 1:运行bootloader主程序,这个程序必须要被安装在MBR中
stage 1_5:在MBR随后的扇区中存放,主要用于与stage2所在分区的文件系统进行交互
stage 2:读取 grub.conf 配置文件,并实现引导功能的扩展
grub配置文件:/boot/grub/grub.conf
defaule: 表示有多个grub引导菜单时,选择哪一个作为默认启动引导菜单;
defaule=0:表示默认选择第一个选项进行配置 ;
timeout: 表示选择菜单的时间,如果过了这个时间没有选择则表示使用默认选项 ;
splashimage: 指定引导菜单中的背景图片的路径 ;
titile: 指定选项的名称 ;
root: 表示kernel和initrd文件所在的分区路径,而不是”根分区”;其格式为;
kernel: 通常是用于指定要运行的内核文件路径,如:/vmlinuz-2.6.32-642.el6.x86_64;另外也可在其后设置相关的内核参数,如:ro表示只读,root表示指定根分区所在路径,关闭selinux等等;
initrd: 为内核运行指定其可用的ramdisk文件,其版本须和内核版本一致;
grub常用的指令:
help:查看命令帮助;
root (DEVICE):指定系统和内核文件所在的分区,如root(hd0,0)。
find (hd0,0) /path/to/file:用于查找对应分区下的文件。常用于当不确认内核文件在哪个分区时,可使用此命令确认文件所在路径;支持tab补全;
kernel /path/to/kernel_file:用于指定要运行的内核文件。
initrd /path/to/kernel_file:指定initrd文件;
boot:以当前配置好的grub配置启动系统;
3、实现kickstart文件制作与光盘镜像制作
定制kickstart 文件:
[[email protected] ~]# yum install system-config-kickstart
检查语法错误:
[[email protected] ~]# ksvalidator anaconda-ks.cfg
准备目录,复制光盘内容到该目录中:
[[email protected] ~]# mkdir /tmp/cdrom
[[email protected] ~]# mkdir /media/cdrom
[[email protected] ~]# mount -r -t iso9660 /dev/cdrom /media/cdrom
[[email protected] ~]# cp -r /media/cdrom/ /tmp/cdrom/
[[email protected] ~]# cd /tmp/cdrom/
[[email protected] cdrom]# cd cdrom/
[[email protected] ~]# chmod u+w isolinux/*
将ks.cfg文件拷贝到/tmp/cdrom中
[[email protected] cdrom]# cp /root/ks.cfg /tmp/cdrom
创建iso镜像
[[email protected] cdrom]# mkisofs -R -J -T -v --no-emul-boot --boot-load-size 4 --boot-info-table -V "CentOS 6 x86_64 boot" -c isolinux/boot.cat -b isolinux/isolinux.bin -o /root/boot.iso cdrom/
以上是关于网络设备初始化主要流程是?的主要内容,如果未能解决你的问题,请参考以下文章