我正在编写一个与英特尔DPDK接口的Rust程序,而且我遇到了一个我不太了解的问题。我当前可以在Rust程序中从DPDK库执行一个函数,但它的结果与用C编写的相同程序不同。
Rust程序输出 -
~/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程序的代码。
Rust 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);
}
}
C 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 中,并调用各种其他init函数。额外输出的触发器来自 eal_common_dev.c 中名为rte_eal_dev_init()
的另一个函数。
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;
}
我发现Rust程序进入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);
}
这给了我Rust中的以下输出 -
~/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 :(得分:1)
我原本以为我没有正确链接到提供 sys / queue.h 信息的内容。在尝试更好地理解链接时,我更改了我的build.rs以获取DPDK的链接 -
$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;
#!/usr/bin/env python **is this in the first line of you python script?**
chmod +x /usr/custom/test.py
对此 -
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");
}
Rust现在链接到所有已编译的DPDK库,而不仅仅是 rte_eal ,其中调用了初始函数。现在,当我执行Rust程序时,我获得与C程序相同的输出 -
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编译为共享库,我就不会遇到这个问题。
感谢Shepmaster,虽然没有直接回答我的问题,但强迫我简化它使得以更加可控的方式解决我的问题变得更加容易。
答案 1 :(得分:-1)
您在continue
之后缩进if
,这是一个视觉提示,它应该是if
块的一部分 - 但编译器不会采用视觉提示。< / p>
您需要将{}
放在if
的块周围,或者继续&#39;将始终执行;
if (driver->type != PMD_PDEV)
{
printf("\nDriver name = %s", driver->name); // Added to track problem
continue;
}
至于不同的结果 - 也许C更快,所以每个核心都会回来并在下一个核心开始之前完成;而在Rust中它较慢,所以它们并行工作并以随机顺序返回?