前言
最近事情做了许多,也包含了许多小事儿,大的部分暂时没有准备好。本周就拼凑着讲一下几个小事儿。
DPDK ring出队是否卡住
节前的时候,组里的同事检视我的代码,提了一个意见。说是rte_ring这个环状队列,被调用批量出队的时候,如果对内里面的个数小于期望的个数,那么会返回0或者卡住。我就写了个demo验证了一下,结果如下:
可以看出,出队时并不会卡住,即使不满足期望个数也会出队实际的个数。
动态库的constructor方法在库被加载时才会被调用
我们知道,如果设置了一个函数的gcc属性为__attribute__(constructor),那么在main函数运行之前就会调用这个函数。
同事在把DPDK的driver库编译为动态库的时候,发现运行的时候很多数据没有正常初始化。然后打印了断点,函数也没有被断到,可以确定对应的函数没有执行。
想来没有加载动态库的时候,这些函数也就在main运行之前不会被调用了,很正常。DPDK的eal参数提供了加载指定驱动的命令选项, 可以通过加载指定的so,后续在运行的时候发现数据正常初始化了。
看了一下这块的代码,
-d LIB.so|DIR Add a driver or driver directory
(can be used multiple times)
int
eal_parse_common_option(int opt, const char *optarg,
struct internal_config *conf)
...
/* force loading of external driver */
case 'd':
if (eal_plugin_add(optarg) == -1)
return -1;
break;
static int
eal_plugin_add(const char *path)
{
struct shared_driver *solib;
solib = malloc(sizeof(*solib));
if (solib == NULL) {
RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
return -1;
}
memset(solib, 0, sizeof(*solib));
strlcpy(solib->name, path, PATH_MAX);
TAILQ_INSERT_TAIL(&solib_list, solib, next);
return 0;
}
int
eal_plugins_init(void)
{
struct shared_driver *solib = NULL;
struct stat sb;
/* If we are not statically linked, add default driver loading
* path if it exists as a directory.
* (Using dlopen with NOLOAD flag on EAL, will return NULL if the EAL
* shared library is not already loaded i.e. it's statically linked.)
*/
if (is_shared_build() &&
*default_solib_dir != '\0' &&
stat(default_solib_dir, &sb) == 0 &&
S_ISDIR(sb.st_mode))
eal_plugin_add(default_solib_dir);
TAILQ_FOREACH(solib, &solib_list, next) {
if (stat(solib->name, &sb) == 0 && S_ISDIR(sb.st_mode)) {
if (eal_plugindir_init(solib->name) == -1) {
RTE_LOG(ERR, EAL,
"Cannot init plugin directory %s\n",
solib->name);
return -1;
}
} else {
RTE_LOG(DEBUG, EAL, "open shared lib %s\n",
solib->name);
solib->lib_handle = eal_dlopen(solib->name);
if (solib->lib_handle == NULL)
return -1;
}
}
return 0;
}
可以看到,在参数解析的时候会把driver对应的路径存起来, 在后面的eal_plugins_init时候调用dlopen加载该动态库。 很多插件的实现原理也是类似,通过加载固定文件夹下的so,触发特定的函数执行,或者是调用so内部的特定函数,实现对应的功能。
destructor在函数异常退出是不会调用被调用
最近在设计一个用户态库的接口,需要对外提供资源的申请释放的接口,资源是通过ioctl调用内核的驱动模块来操作的,也就是多个用户态进程会共同使用内核的资源。我本来是想着,如果使用接口的进程异常退出了,那么就由用户态的库自动释放这些资源。本来我是想着使用attribute(destructor)属性的函数来实现已申请的资源的释放的。实验了一下,发现此路不同。
show you code:
#include <stdio.h>
#include <stdlib.h>
/*
用于验证异常情况下, destructor是否会被调用。
结论:
进程异常(被kill)退出,不会调用destructor函数。
*/
__attribute__((constructor)) static void beforeFunction()
{
printf("beforeFunction\n");
}
__attribute__((destructor)) static void afterFunction()
{
printf("afterFunction\n");
}
void main(void)
{
int i = 0;
int times = 60;
while (i++ < times)
{
printf("current i = %d\r\n", i);
sleep(1);
}
return;
}
编译运行之后,我使用kill -9 命令杀死这个进程,可以看到,并没有输出afterFunction。
device_create创建设备文件
之前在学习驱动的时候,前面的文章《字符设备驱动》使用的mknod命令手动创建了设备文件。这周看了之前的驱动代码, 使用device_create函数创建了设备文件。
在调用device_create前要先用class_create创建一个类。类这个概念在Linux中被抽象成一种设备的集合。类在/sys/class目录中。
root@keep-VirtualBox:/sys/class# ls /sys/class/
ata_device block devlink drm_dp_aux_dev hidraw intel_scu_ipc mem net power_supply ptp remoteproc scsi_generic thermal vc watchdog
ata_link bsg dma extcon hwmon iommu misc pci_bus ppdev pwm rfkill scsi_host tpm vfio wwan
ata_port devcoredump dma_heap firmware i2c-adapter leds mmc_host pci_epc ppp rapidio_port rtc sound tpmrm virtio-ports
backlight devfreq dmi gpio i2c-dev lirc msr phy pps rc scsi_device spi_master tty vtconsole
bdi devfreq-event drm graphics input mdio_bus nd powercap printer regulator scsi_disk spi_slave usb_role wakeup
root@keep-VirtualBox:/sys/class#
主要代码如下:
...
globalmem_devp->dev_class = class_create(THIS_MODULE, "driver_dev");
if (IS_ERR(globalmem_devp->dev_class)) {
printk("class create error\r\n");
ret = -EBUSY;
goto fail_malloc;
}
devices = device_create(globalmem_devp->dev_class, NULL, MKDEV(globalmem_major, 0), NULL, "globalmem");
if(NULL == devices){
printk("device_create error\r\n");
ret = -EBUSY;
class_destroy(globalmem_devp->dev_class);
goto fail_malloc;
}
...
安装之后, 可以在/sys/class和/dev下找到driver_dev和globalmem
行动,才不会被动!
欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。
博客地址: fishmwei.github.io
掘金主页: juejin.cn/user/208432…