2016-08-23 14 views
0

我正在编写一个与英特尔的DPDK接口的Rust程序,并且我遇到了一个我不太明白的问题。我目前可以从在锈病程序DPDK库执行的功能,但它在从写入C.DPDK函数具有不同的输出,当从Rust中调用时比从C中输出

锈病程序输出相同的程序的结果不同 -

~/Dev/rust_eal_init_test$ sudo target/debug/rust_eal_init_test 
EAL: Detected 8 lcore(s) 
EAL: No free hugepages reported in hugepages-2048kB 
EAL: Probing VFIO support... 
~/Dev/rust_eal_init_test$ 

C程序输出 -

~/Dev/c_eal_init_test$ sudo build/c_eal_init_test 
EAL: Detected 8 lcore(s) 
EAL: No free hugepages reported in hugepages-2048kB 
EAL: Probing VFIO support... 
PMD: bnxt_rte_pmd_init() called for (null) 
EAL: PCI device 0000:00:19.0 on NUMA socket -1 
EAL: probe driver: 8086:153a rte_em_pmd 
EAL: PCI device 0000:04:00.0 on NUMA socket -1 
EAL: probe driver: 8086:1533 rte_igb_pmd 
~/Dev/c_eal_init_test$ 

DPDK已被编译为我在Rust中链接到的静态库。下面是Rust和C程序的代码。

锈main.rs -

extern crate libc; 

use std::env; 
use std::process::exit; 
use std::ffi::CString; 
use libc::{c_int, c_char,}; 

extern { 
    pub fn rte_eal_init(argc: c_int, argv: *mut *mut c_char) -> c_int; 
} 

// librte_eal 
pub fn dpdk_rte_eal_init(argc: i32, argv: Vec<String>) -> i32 { 
    let mut args: Vec<*mut c_char> = argv.iter().map(|x| CString::new(x.clone()).unwrap().into_raw()).collect(); 
    let retc: c_int = unsafe { rte_eal_init(argc as c_int, args.as_mut_ptr()) }; 
    let ret: i32 = retc as i32; 
    ret 
} 

fn main() { 
    let args: Vec<String> = env::args().collect(); 

    let ret: i32 = dpdk_rte_eal_init(args.len() as i32, args); 
    if ret < 0 { 
     exit(ret); 
    } 
} 

Ç的main.c -

#include <stdio.h> 
#include <string.h> 
#include <rte_eal.h> 
#include <rte_debug.h> 

int 
main(int argc, char **argv) 
{ 
    int ret; 

    ret = rte_eal_init(argc, argv); 
    if (ret < 0) 
     rte_panic("Cannot init EAL\n"); 

    return 0; 
} 

我已经做了由翻翻DPDK来源并添加打印语句,看看那里的东西不同一番调查。 rte_eal_init()函数位于eal.c中,并调用各种其他初始化函数。额外输出的触发来自rte_eal_dev_init()中的另一个函数eal_common_dev.c

rte_eal_dev_init() -

int 
rte_eal_dev_init(void) 
{ 
    struct rte_devargs *devargs; 
    struct rte_driver *driver; 

    /* 
    * Note that the dev_driver_list is populated here 
    * from calls made to rte_eal_driver_register from constructor functions 
    * embedded into PMD modules via the PMD_REGISTER_DRIVER macro 
    */ 

    /* call the init function for each virtual device */ 
    TAILQ_FOREACH(devargs, &devargs_list, next) { 

     if (devargs->type != RTE_DEVTYPE_VIRTUAL) 
      continue; 

     if (rte_eal_vdev_init(devargs->virt.drv_name, 
        devargs->args)) { 
      RTE_LOG(ERR, EAL, "failed to initialize %s device\n", 
        devargs->virt.drv_name); 
      return -1; 
     } 
    } 

    /* Once the vdevs are initalized, start calling all the pdev drivers */ 
    TAILQ_FOREACH(driver, &dev_driver_list, next) { 
     if (driver->type != PMD_PDEV) 
      continue; 
     /* PDEV drivers don't get passed any parameters */ 
     driver->init(NULL, NULL); 
    } 
    return 0; 
} 

我发现是生锈程序进入rte_eal_dev_init()功能,但从未进入的TAILQ_FOREACH()宏循环。如果我要加正上方和像这样的宏观调控下打印语句 -

printf("Test before TAILQ_FOREACH\n"); 
TAILQ_FOREACH(driver, &dev_driver_list, next) { 
    printf("Test in TAILQ_FOREACH\n"); 
    if (driver->type != PMD_PDEV) 
     continue; 
    /* PDEV drivers don't get passed any parameters */ 
    driver->init(NULL, NULL); 
} 

这使我在锈下面的输出 -

~/Dev/rust_eal_init_test$ sudo target/debug/rust_eal_init_test 
EAL: Detected 8 lcore(s) 
EAL: No free hugepages reported in hugepages-2048kB 
EAL: Probing VFIO support... 
Test before TAILQ_FOREACH 
~/Dev/rust_eal_init_test$ 

而下面的输出用C -

~/Dev/c_eal_init_test$ sudo build/c_eal_init_test 
EAL: Detected 8 lcore(s) 
EAL: No free hugepages reported in hugepages-2048kB 
EAL: Probing VFIO support... 
Test before TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
PMD: bnxt_rte_pmd_init() called for (null) 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
EAL: PCI device 0000:00:19.0 on NUMA socket -1 
EAL: probe driver: 8086:153a rte_em_pmd 
EAL: PCI device 0000:04:00.0 on NUMA socket -1 
EAL: probe driver: 8086:1533 rte_igb_pmd 
~/Dev/c_eal_init_test$ 

我发现TAILQ_FOREACH()定义在sys/queue.h。据我了解,链接到一个静态库不应该导致与动态链接到其他库的问题。它是否正确?

+0

这听起来像你可能没有将'TAIL_Q_FOREACH',这可能是一个宏生成一个循环,转换成锈 - 但你没有显示任何代码,所以不能告诉。我不希望这是一个链接问题,如果你得到它运行。 –

+0

正如目前所写,这个问题应该是封闭的,因为:*寻求调试的帮助(“为什么不是这个代码工作?”)必须包含所需的行为,特定的问题或错误以及重现它所需的最短代码质疑自己。没有明确问题陈述的问题对其他读者无用。* [编辑]您的问题以产生[MCVE]。 – Shepmaster

+2

您的'printf' **完全改变循环**的行为。这就是为什么if语句应该是强制性的。 – Shepmaster

回答

1

我原本以为我没有正确链接到提供的信息sys/queue.h。在尝试理解更好地联系起来,我改变了我的build.rs的链接,从该DPDK -

fn main() { 
    println!("cargo:rustc-link-lib=static=rte_eal"); 
    println!("cargo:rustc-link-search=native=<Path to RTE_SDK>/x86_64-native-linuxapp-gcc/lib"); 
} 

为了这一点 -

fn main() { 
    println!("cargo:rustc-link-lib=static=dpdk"); 
    println!("cargo:rustc-link-search=native=<Path to RTE_SDK>/x86_64-native-linuxapp-gcc/lib"); 
} 

锈现在链接到被编译,而不是所有DPDK库只是rte_eal其中的初始函数被调用。现在,当我执行我的防锈程序,我得到的输出相同的C程序 -

~/Dev/rust_eal_init_test$ sudo target/debug/rust_eal_init_test 
EAL: Detected 8 lcore(s) 
EAL: No free hugepages reported in hugepages-2048kB 
EAL: Probing VFIO support... 
Test before TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
PMD: bnxt_rte_pmd_init() called for (null) 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
Test in TAILQ_FOREACH 
EAL: PCI device 0000:00:19.0 on NUMA socket -1 
EAL: probe driver: 8086:153a rte_em_pmd 
EAL: PCI device 0000:04:00.0 on NUMA socket -1 
EAL: probe driver: 8086:1533 rte_igb_pmd 
~/Dev/rust_eal_init_test$ 

我没想到的静态库需要另一个之一被列入可执行文件为它工作。我也从这个假设,如果我要编译DPDK作为共享库,我不会有这个问题。

感谢Shepmaster,虽然没有直接回答我的问题,但是迫使我简化它,使得以更可控的方式排除我的问题更容易。

0

您在if之后缩进了continue,这是一个视觉提示,它应该是if块的一部分 - 但编译器不会提供视觉提示。

你需要把{}围绕if块,或“继续”将是总是执行;

if (driver->type != PMD_PDEV) 
{ 
    printf("\nDriver name = %s", driver->name); // Added to track problem 
    continue; 
} 

而对于不同的结果 - 也许C是刚更快,因此每个核心回来,甚至被开始下一个之前完成;而在Rust中它比较慢,所以它们并行工作并以随机顺序回来?

+1

这实际上并不回答Rust版本输出与C版本不同的基本问题。根据叙述,在*破坏的'continue'陈述被添加之前,输出不同*。 – Shepmaster

+0

我不认为问题是围绕结果排序,而是围绕缺失的行(如'bnxt_rte_pmd_init'或'probe driver'),尽管我很欣赏狡猾的诋毁非C/C++语言的尝试。 – Shepmaster

相关问题