zoukankan      html  css  js  c++  java
  • dpdk初始化

    rte_eal_init
    │
    ├──rte_cpu_is_supported:检查cpu是否支持
    │
    ├──rte_atomic32_test_and_set:操作静态局部变量run_once确保函数只执行一次
    │
    ├──pthread_self() 获取主线程的线程ID,只是用于打印
    │
    ├──eal_reset_internal_config:初始化内部全局配置变量struct internal_config
    │
    ├──eal_log_level_parse 解析命令行参数,只处理“--log-level”
    │   │
    │   └──eal_parse_log_level 填充struct rte_logs rte_logs全局log控制变量
    │
    ├──rte_eal_cpu_init:赋值全局结构struct lcore_config
    │   │
    │   ├──rte_eal_get_configuration:获取全局配置结构struct rte_config,初始指向全局变量early_mem_config
    │   │
    │   ├──eal_cpu_detected
    │   │   │
    │   │   └──如果文件“/sys/devices/system/cpu/cpu%u/topology/core_id”存在,则存在此编号的cpu
    │   │
    │   ├──eal_cpu_core_id
    │   │   │
    │   │   └──eal_parse_sysfs_value:读取文件“/sys/devices/system/cpu/cpu%u/topology/core_id”,
    │   │         获取core number onsocket for this lcore
    │   │
    │   ├──eal_cpu_socket_id
    │   │   │
    │   │   └──如果目录“/sys/devices/system/node/node%u/cpu%u”存在,得到physical socket id for this lcore
    │   │
    │   └──计数得到number of available logical cores,保存在struct rte_config.lcore_count中
    │
    ├──eal_parse_args:解析处理EAL的命令行参数,赋值struct internal_config 结构的相关字段
    │
    ├──eal_plugins_init (EAL的“-d”选项可以指定需要载入的动态链接库)
    │   │
    │   ├──如果全局变量 default_solib_dir 所指的Default path of external loadable drivers有效
    │   │   │
    │   │   └──eal_plugin_add
    │   │         │
    │   │         ├──malloc一个struct shared_driver结构,拷贝路径名称
    │   │         │
    │   │         └──将此struct shared_driver结构挂载到List of external loadable drivers中 solib_list
    │   │
    │   └──遍历solib_list上挂载的所有struct shared_driver结构
    │         │
    │         ├──如果当前struct shared_driver结构所保存的路径是目录
    │         │   │
    │         │   └──eal_plugindir_init
    │         │         │
    │         │         └──对目录中的每个普通文件,执行eal_plugin_add
    │         │                (将文件挂载到Listof external loadable drivers的尾部,待接下来的遍历循环进行处理)
    │         │
    │         └──否则,是共享库的情况
    │               │
    │               └──调用dlopen打开指定的动态链接库
    │
    ├──eal_option_device_parse (EAL的“-b、-w、--vdev”选项可以指定需要解析支持的设备 eal_option_device_add)
    │   │
    │   ├──如果全局变量链表有挂载指定支持的设备的话devopt_list
    │   │   │
    │   │   └──rte_devargs_parse 解析后,存放到全局链表 devargs_list 里面
    │   │         │
    │   │         ├──calloc一个struct rte_devargs 结构
    │   │         │
    │   │         ├──rte_devargs_parse读取系统所有设备,如果能找到表示属于合法设备
    │   │         │
    │   │         └──将此struct rte_devargs结构挂载到devargs_list
    │   │
    │   └──解析后的struct device_option从devopt_list删除
    │
    ├──rte_config_init
    │   │
    │   ├──主进程的情况(RTE_PROC_PRIMARY) rte_config.mem_config这块内存,在初始化巨页之前,使用本地全局变量&early_mem_config临时使用
    │   │   │      在rte_eal_config_create里面,rte_config.mem_config的内存改为配置文件/var/run/config,用来主从进程共享使用.
    │   │   │
    │   │   ├──rte_eal_config_create
    │   │   │      │
    │   │   │      ├──eal_runtime_config_path:获取runtime配置文件路径,如“/var/run/config”
    │   │   │      │
    │   │   │      ├──如果EAL配置了巨页映射的虚拟地址的话,在这里把它保存到 rte_mem_cfg_addr 变量里面
    │   │   │      │
    │   │   │      ├──打开文件,上锁,mmap映射文件到内存
    │   │   │      │
    │   │   │      ├──将early configuration structure(全局变量early_mem_config)拷贝到此内存中,
    │   │   │      │   rte_config.mem_config指向这块内存,early_mem_config在巨页没初始化之前,用来当做早期简单配置使用的.
    │   │   │      │
    │   │   │      └──映射地址保存在rte_config.mem_config->mem_cfg_addr中,用于从应用将来映射到相同的地址
    │   │   │
    │   │   └──eal_update_mem_config 更新rte_config里面的rte_mem_config legacy_mem和single_file_segments变量,让从进程可以读取这个信息eal_update_internal_config
    │   │   
    │   └──从进程的情况(RTE_PROC_SECONDARY) 从进程先mmap /var/run/config,然后读取主进程的rte_mem_cfg_addr地址,最后在重新mmap /var/run/config,
    │         │   这样做的目的是保证主从进程的rte_mem_cfg_addr虚拟地址和物理地址都是完全一样的.
    │         │
    │         ├──rte_eal_config_attach
    │         │   │
    │         │   ├──eal_runtime_config_path
    │         │   │
    │         │   ├──打开文件,mmap映射文件到内存
    │         │   │
    │         │   └──rte_config.mem_config指向映射的内存
    │         │
    │         ├──rte_eal_mcfg_wait_complete
    │         │   │
    │         │   └──如果struct rte_mem_config结构的magic成员没有被写成RTE_MAGIC,就继续等待
    │         │          (主应用ready后会将struct rte_mem_config结构的magic成员写成RTE_MAGIC)
    │         │
    │         ├──rte_eal_config_reattach
    │         │      │
    │         │      ├──从前面mmap映射文件中获取主应用mmap的映射地址(即rte_config.mem_config->mem_cfg_addr)
    │         │      │
    │         │      ├──munmap解除先前的映射
    │         │      │
    │         │      ├──指定主应用映射地址重新执行mmap映射,如果最终映射地址和指定映射地址不一致,则出错退出
    │         │      │
    │         │      └──将rte_config.mem_config指向重新映射的内存
    │         │
    │         └──eal_update_internal_config读取主进程初始化的内存配置,保存到本地的internal_config.legacy_mem和internal_config.single_file_segments 
    │
    ├──rte_eal_intr_init 初始化中断系统,dpdk把中断注册到epoll里面,通过epoll来处理发送的中断事件
    │   │
    │   ├──初始化global interrupt source head (struct rte_intr_source_list intr_sources)
    │   │
    │   ├──创建pipe,主要是用来唤醒eal_intr_thread_main重建中断列表,一般在用户注册了中断事件后,会write pipe,epoll read后重建中断列表
    │   │
    │   └──创建线程来等待处理中断,线程执行函数为eal_intr_thread_main
    │      │
    │      └──线程运行循环
    │            │
    │            ├──epoll_create:创建epoll文件描述符
    │            │
    │            ├──epoll_ctl:把前面创建的the read end of the pipe,添加到epoll wait list中
    │            │
    │            ├──遍历以global interrupt source head为头部的struct rte_intr_source结构链表
    │            │   │
    │            │   ├──如果当前struct rte_intr_source结构没有挂载的callback函数,跳过
    │            │   │
    │            │   └──把所有的uio device file descriptor,添加到epoll wait list中
    │            │
    │            ├──eal_intr_handle_interrupts
    │            │   │
    │            │   └──循环
    │            │         │
    │            │         ├──epoll_wait:wait for an I/O event on an epoll file descriptor
    │            │         │
    │            │         ├──eal_intr_process_interrupts
    │            │         │   │
    │            │         │   └──遍历所有发生的I/O event
    │            │         │         │
    │            │         │         ├──如果the read end of the pipe可用,执行read操作,函数返回
    │            │         │         │    (此时会rebuild the wait list)
    │            │         │         │
    │            │         │         ├──遍历struct rte_intr_source结构链表,查找当前I/O event对应的structrte_intr_source结构
    │            │         │         │
    │            │         │         ├──根据interrupt handle type(uio/alarm/…),确定需要读取的字节长度
    │            │         │         │
    │            │         │         ├──执行文件read操作
    │            │         │         │
    │            │         │         └──如果read数据成功,执行当前struct rte_intr_source结构挂载的所有callback函数
    │            │         │
    │            │         └──调用eal_intr_process_interrupts返回负数,本次中断处理结束返回
    │            │
    │            └──关闭epoll文件描述符
    │
    ├──rte_mp_channel_init 创建主从进程通信socket接口,使用AF_UNIX socket 类型,处理任务 mp_handle
    │   │
    │   ├──初始化socket路径 /var/run/mp_socket
    │   │
    │   ├──打开目录/var/run 加锁
    │   │
    │   ├──创建socket,主进程使用/var/run/mp_socket,从进程使用/var/run/mp_socket_getpid_rte_rdtsc, fd使用全局变量保存mp_fd
    │   │
    │   └──创建mp处理进程 mp_handle
    │
    ├──rte_mp_dev_hotplug_init 注册主从进程通信的消息处理回调钩子,该动作是承接rte_mp_channel_init,
    │   │                      rte_mp_channel_init初始化了处理任务mp_handle-->process_msg-->查找hotplug action
    │   │
    │   ├──主进程流程
    │   │   │
    │   │   ├── malloc 一个struct action_entry
    │   │   │
    │   │   ├── 初始化action_entry的action_name(EAL_DEV_MP_ACTION_REQUEST)和action(handle_secondary_request)
    │   │   │
    │   │   └── 增加action_entry到全局链表中action_entry_list
    │   │
    │   └──从进程流程
    │       │
    │       ├── malloc 一个struct action_entry
    │       │
    │       ├── 初始化action_entry的action_name(EAL_DEV_MP_ACTION_REQUEST)和action(handle_primary_request)
    │       │
    │       └── 增加action_entry到全局链表中action_entry_list
    │
    ├──rte_bus_scan 扫描所有已注册设备的总线,主要有pci bus,还有其他厂家提供的总线,如DPAA bus,Intel FPGA bus
    │       │
    │       ├──循环获取设备总线链表 rte_bus_list
    │       │
    │       └──对每一个注册到的设备总线最新scan
    │           │
    │           ├──设备总线注册使用RTE_REGISTER_BUS
    │           │
    │           └──设备bus注册需要提供scan,probe,find_device,plug,unplug,parse,dev_iterate等函数实现,pci总线是 rte_pci_bus
    │
    ├──初始化系统巨页 
    │   │
    │   ├──主进程 eal_hugepage_info_init:赋值struct hugepage_info数组(internal_config.hugepage_info)
    │   │   │
    │   │   ├──hugepage_info_init 读取系统巨页的信息,填充到internal_config.hugepage_info数组里面如果没有巨页数量可用,这里返回失败,
    │   │   │    否则,hugepage_info数组里面按照巨页大小排序存储hugepage_info[0]>hugepage_info[1]>hugepage_info[2],这里是巨页大小不是巨页数量
    │   │   │     │
    │   │   │     ├── 打开系统的/sys/kernel/mm/hugepages目录,里面存在系统当前使用的巨页大小对应的信息
    │   │   │     │
    │   │   │     ├── 遍历/sys/kernel/mm/hugepages子目录信息,如果子目录以hugepages-开头,则继续处理,否则不处理,
    │   │   │     │   一般有hugepages-2048kB或者hugepages-1048576kB两种存在
    │   │   │     │
    │   │   │     ├── /sys/kernel/mm/hugepages子目录数量不能超过dpdk运行的最大数,目前为3个
    │   │   │     │
    │   │   │     ├── 以数组方式,把系统不同巨页信息按顺序存放在internal_config.hugepage_info[]数组里面
    │   │   │     │    │
    │   │   │     │    └── get_hugepage_dir 根据系统巨页的大小,获取系统巨页mount路径
    │   │   │     │         │
    │   │   │     │         ├── 读取系统的/proc/mounts目录,里面存放了用户所有mount信息
    │   │   │     │         │
    │   │   │     │         ├── 获取默认的巨页大小,说白了就是获取系统默认的巨页大小,一般是2MB, 获取方式,cat /proc/meminfo |grep Hugepagesize
    │   │   │     │         │
    │   │   │     │         └── 循环判断/proc/mounts所有信息,如果有hugetlbfs的标识,表示是系统的巨页挂载点
    │   │   │     │              │ 
    │   │   │     │              ├── 一条mount信息包含四个选项,按顺序分别是device、mountpt、fstype、options分别按顺序存放到splitstr指针数组里面
    │   │   │     │              │ 
    │   │   │     │              ├── 如果用户设置了启动参数--huge-dir选项,就只检查这个目录是否存在
    │   │   │     │              │ 
    │   │   │     │              └── 查找mount信息里面的options,是否存在"pagesize="选项,如果是,则直接使用该页大小,否则使用默认的页大小
    │   │   │     │         
    │   │   │     ├── 系统总的可用巨页数量保存到internal_config.num_hugepage_sizes  
    │   │   │     │    
    │   │   │     └── 到此为止,internal_config里面关于巨页相关的变量基本都初始化了 
    │   │   │
    │   │   └──如果设置了不共享巨页信息,直接返回,否则下面会创建一个文件,把internal_config.hugepage_info信息存放到eal_hugepage_info_path里面,
    │   │      让从进程可以attach,共享同一块内存
    │   │       │
    │   │       └──create_shared_memory 创建共享文件/var/run/hugepage_info,把internal_config.hugepage_info保存进去,让从进程可以读取
    │   │
    │   └──从进程 eal_hugepage_info_read
    │              │
    │              └──读取主进程存放在/var/run/hugepage_info文件里面的信息,读取出来保存到本地的internal_config.hugepage_info
    │
    ├──rte_srand(rte_rdtsc()) 将当前时间作为种子,产生伪随机数序列
    │
  • 相关阅读:
    Leetcode 349. Intersection of Two Arrays
    hdu 1016 Prime Ring Problem
    map 树木品种
    油田合并
    函数学习
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 102. Binary Tree Level Order Traversal
    Leetcode 101. Symmetric Tree
    poj 2524 Ubiquitous Religions(宗教信仰)
    pat 1009. 说反话 (20)
  • 原文地址:https://www.cnblogs.com/ggzhangxiaochao/p/12098653.html
Copyright © 2011-2022 走看看