基于qemu-kvm-0.12.1.2-2.160.el6_1.8.src.rpm
虚拟网卡类型为virtio-net-pci
virtio网卡设备对应的命令行参数为
-device virtio-net-pci,netdev=hostnet0,id=net0,mac=00:16:36:01:c4:86,bus=pci.0,addr=0x3
1. 在parse命令行的时候,qemu把所有的-device选项parse后保存到qemu_device_opts中
2. 调用module_call_init(MODULE_INIT_DEVICE); 往系统中添加所有支持的设备类型
virtio-net-pci的设备类型信息如下(virtio-pci.c):
static PCIDeviceInfo virtio_info[] = {
{
.qdev.name = "virtio-net-pci",
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_net_init_pci,
.exit = virtio_net_exit_pci,
.romfile = "pxe-virtio.bin",
.qdev.props = (Property[]) {
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy,
net.txtimer, TX_TIMER_INTERVAL),
DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy,
net.txburst, TX_BURST),
DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
DEFINE_PROP_END_OF_LIST(),
},
.qdev.reset = virtio_pci_reset,
}
};
3. 调用qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) 创建命令行上指定的设备
4. device_init_func调用qdev_device_add(opts)
5. qdev_device_add函数的流程如下:
a) 调用qemu_opt_get(opts, "driver")获取driver选项,这里应该是virtio-net-pci
b) 调用qdev_find_info(NULL, driver)来获取注册的DeviceInfo,这里应该是上面virtio_info里面关于
virtio-net-pci的结构
c) 调用qemu_opt_get(opts, "bus")获取bus路径,以/分隔各组件。这里是pci.0
d) 如果bus路径不为空,则调用qbus_find(path)来获取bus实例(BusState结构)
qbus_find函数的流程如下:
d.1) 先找到路径中的根bus,如果路径以/开头,则根bus为main_system_bus,否则,使用
qbus_find_recursive(main_system_bus, elem, NULL)来查找。这里的elem = "pci.0"
d.2) 如果整个路径已经完成,则返回当前bus
d.2) parse出下一个组件,调用qbus_find_dev查找对应的设备
d.3) parse出下一个组件,调用qbus_find_bus查找属于上层设备的子bus
d.4) 返回步骤2
由于这里的值是pci.0,因此其实只进行了一次qbus_find_recursive调用
e) 如果bus路径为空,则调用qbus_find_recursive(main_system_bus, NULL, info->bus_info)来获取bus
实例。这里的info是driver("virtio-net-pci")所对应的DeviceInfo,即最上面的结构
virtio-pci的初始化步骤是virtio_pci_register_devices -> pci_qdev_register_many ->
pci_qdev_register,在该函数中,会设置info->bus_info = &pci_bus_info,这样就把PCIDeviceInfo
和pci的BusInfo联系起来了
qbus_find_recursive是一个递归函数,其流程如下:
e.1) 如果当前bus的名称和指定的名称相同(指定名称不为空的情况下),并且当前bus指向的bus info和
指定的bus info相同(指定bus info不为空的情况下),则返回当前bus
e.2) 这里是一个两重循环:
对于当前bus所有附属的设备(bus->children为链表头)
对于当前设备所有的附属bus(dev->child_bus为链表头)
调用qbus_find_recursive函数
f) 调用qdev_create_from_info(bus, info)来创建设备,返回的是DeviceState结构。这里其实返回的是
一个VirtIOPCIProxy实例,因为create的时候是根据qdev.size来分配内存大小的。
g) 如果qemu_opts_id(opts)不为空,则设置qdev->id
h) 调用qemu_opt_foreach(opts, set_property, qdev, 1)来设置设备的各种属性
i) 调用qdev_init来初始化设备。
j) qdev_init会调用dev->info->init函数。这里实际调用的函数是virtio_net_init_pci
在这里也大致描述一下bus pci.0是如何生成的
1. 在main函数里面很前面的地方会调用module_call_init(MODULE_INIT_MACHINE);
2. module_call_init会调用所有已注册QEMUMachine的init函数。该版本的qemu是注册了
pc_machine_rhel610, pc_machine_rhel600, pc_machine_rhel550, pc_machine_rhel544,
pc_machine_rhel540这几个 (pc.c)
3. 这些Machine的init函数(pc_init_rhel600, ...)都会调用到pc_init_pci函数
4. pc_init_pci回调用pc_init1,pc_init1在pci_enabled情况下会调用i440fx_init (piix_pci.c)
5. i440fx_init首先会调用qdev_create(NULL, "i440FX-pcihost")创建一个host device
6. 然后调用pci_bus_new在该设备下面创建一个附属的pci bus。在调用该函数时,传递的name为NULL。
下面再看看这个bus的名称怎么会变成pci.0的
7. pci_bus_new调用pci_bus_new_inplace(bus, parent, name, devfn_min),其中bus指向刚分配的
内存,parent是前面创建的host device,name为NULL,devfn_min为0
8. pci_bus_new_inplace会调用qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name),
注意这里的第二个参数是&pci_bus_info
9. qbus_create_inplace在开始的地方会为该bus生成一个名称。因为传递进来的name为NULL,并且
parent(那个host device)的id也为NULL,因此分支会跳到下面的代码
len = strlen(info->name) + 16;
buf = qemu_malloc(len);
len = snprintf(buf, len, "%s.%d", info->name,
parent ? parent->num_child_bus : 0);
for (i = 0; i < len; i++)
buf[i] = qemu_tolower(buf[i]);
bus->name = buf;
10. 在该段代码中,info就是之前pci_bus_new_inplace调用时传进来的&pci_bus_info,info->name是
字符串"PCI"。并且,因为这是在host device上创建的第一个bus,因此parent->num_child_bus = 0,
最后经过小写处理之后,该bus的名称就成为了"pci.0"
这一段分析所对应的bus/device layout如下
main-system-bus ----> i440FX-pcihost ----> pci.0
QEMU虚拟网卡设备的创建流程相关推荐
- 网络虚拟化——QEMU虚拟网卡
写在前面 网络虚拟化曾经只是内核虚拟化功能开发者才会关注的技术.但随着云计算模式和云原生概念的推广,云上业务的部署形态都已转向了虚拟机和容器,而两者都依赖网络虚拟化技术提供高性能网络功能,因此虚拟网络 ...
- 隐藏在计算机网卡怎样删除,如何卸载电脑中隐藏的虚拟网卡设备
虚拟网卡主要是建立远程计算机间的局域网,在此虚拟的局域网上能进行所有物理存在的局域网的操作,可以互相访问,可以联网玩游戏.当需要卸载电脑系统中的虚拟网卡时,在设备管理器中无法查看到虚拟网卡设备,那么怎 ...
- 服务器虚拟网卡卸载不掉,怎么彻底卸载虚拟网卡设备。 彻底卸载虚拟网卡设备的方法。...
今天给大家带来怎么彻底卸载虚拟网卡设备.,彻底卸载虚拟网卡设备的方法.,让您轻松解决问题.网友求助:求助如何卸载虚拟网卡? 具体方法如下:1 使用Win+R调出运行,在其中输入:devmgmt.msc ...
- linux虚拟网卡tun,Centos7 创建虚拟网卡(tun/tap)
创建网卡.创建网桥并建立桥接 [root@kolla ~]# cat create.sh create_br(){ tunctl -t storage -u root brctl addbr virb ...
- STM32MP157 | 虚拟网卡设备驱动
一.网络设备驱动 1. 概念 网络设备是Linux的第三类标准设备,没有对应的设备文件,使用内部设备名访问.网络设备及其驱动属于整个TCP/IP协议层的一部分,实现遵循TCP/IP协议栈的要求. 网络 ...
- linux TUN 虚拟网卡设备
[网络虚拟化技术(二): TUN/TAP MACVLAN MACVTAP] https://blog.kghost.info/2013/03/27/linux-network-tun/ TUN 设备是 ...
- linux上使用tun/tap设备模拟一个虚拟网卡,并将该虚拟网卡连接到新创建的网桥上
目录 linux上使用tun/tap设备模拟一个虚拟网卡,并将该虚拟网卡连接到新创建的网桥上 一.tun/tap设备简介 二.在linux上使用tun/tap设备模拟一个虚拟网卡 三. 创建网桥连接到 ...
- 11-S3C2440驱动学习(五)嵌入式linux-网络设备驱动(一)虚拟网卡驱动程序
本节是网卡驱动的入门基础部分,移植移植DM9000C网卡驱动程序 请看下节:移植DM9000C网卡驱动程序http://blog.csdn.net/fengyuwuzu0519/article/det ...
- sstap tun虚拟网卡没有安装_虚拟设备之TUN和TAP
前言 最近尝试了下 Zerotier,感觉还挺好用的, 比较好奇它的实现原理,查了下,遂有了下文. TAP与TUN是什么 不同于硬件物理网卡,TAP/TUN 是在 Linux 内核 2.4.x 版本之 ...
最新文章
- Spring Bean四种注入方式(Springboot环境)
- 总结403到504的常用问题
- 野火 stm32f429 pcb_PCB板价格是如何核算的
- Google员工自述:在哈佛教书和在Google工作的差别
- 将数据转化为API,OpenDataSoft获540万美元A轮融资
- 最小二乘法C#实现,简单代码
- Java技巧: 根据网址查询DNS/IP地址
- Python 数据分析三剑客之 NumPy(二):数组索引 / 切片 / 广播 / 拼接 / 分割
- 设计模式原则(3)--Dependency Inversion Principle(DIP)--依赖倒转原则
- 盖得化工--selenium翻页测试
- C中得到4号错误(中断),怎么办
- 【LeetCode-SQL】1336. 每次访问的交易次数
- 正则化及正则化项的理解
- 车规电阻AEC-Q200测试项目及元器件检测设备
- Apache Struts2远程代码执行漏洞(S2-019)复现
- php禁用session和cookies,session与cookie的区别是什么?如果客户端禁用了cookie功能,将会对session有什么影响?...
- QT在界面背景图设置后运行显示黑屏
- STM32 PWM的理解
- 寻迹小车笔记——红外对管(TCRT5000)原理
- VUE“粘性”阅读进度条
热门文章
- 手机webapp meta标签 (全屏)
- 零积分下载,2014年辛星mysql教程秋季版第一本已经完工,期待您的支持
- 三行代码接入,社交软件打字时底下弹出的表情布局,自定义ViewPager+页面点标+各种功能的android小框架。...
- 原型继承与属性拷贝的混合应用
- 基于nginx的tomcat负载均衡和集群(超简单)
- 在vs2005中使用loki的方法
- Css的filter常用滤波器属性及语句大全
- NHibernate one-to-one
- Web 2.0背后的长尾理论
- 设计模式实战 - 责任链模式