1

我正在 FreeBSD 10.0 上安装新的 newbuf 驱动程序。使用 make 编译后,驱动程序.ko 文件已创建,并且 kldload 可以成功加载。kldload 返回 0,我可以在 kldstat 输出中看到该设备。尝试使用驱动程序打开 /dev/** 文件时,该文件不存在。

我认为这个 /dev/** 文件应该由位于 device_attach 成员方法中的 make_dev 函数创建。测试kldload是否达到这个附加功能;当编写 printf 和 uprintf 来调试驱动程序时,我在控制台上看不到任何输出,也看不到 dmesg 输出。但问题是在 device_identify 和 device_probe 函数的开头(在局部变量定义之后)编写 printf 之后,我在控制台和 dmesg 上都看不到任何输出。

我的问题是,即使物理驱动程序有问题(未定位等),我是否应该在开始课程时 kldload 调用的 device_identify 成员函数中看到 printf 的输出(我认为)?

使用 printf 调试 newbuf 驱动程序时是否有错误(我还尝试了 hello_world 设备驱动程序,在此驱动程序中我可以在 dmesg 中输出 printf)?

主要是如何测试/调试这个驱动程序的 kldload 进程?

在我的驱动程序代码的某些部分下面(我认为至少我应该看到 MSG1,但我看不到):

struct mydrv_softc 
{
    device_t        dev;
};

static devclass_t mydrv_devclass;

static struct cdevsw mydrv_cdevsw = {
    .d_version  = D_VERSION,
    .d_name     = "mydrv",
    .d_flags    = D_NEEDGIANT,
    .d_open     = mydrv_open,  
    .d_close    = mydrv_close, 
    .d_ioctl    = mydrv_ioctl,
    .d_write    = mydrv_write,
    .d_read     = mydrv_read
};


static void mydrv_identify (driver_t *driver, device_t parent) {
    devclass_t dc;
    device_t child;

    printf("MSG1: The process inside the identfy function.");

    dc = devclass_find("mydrv");
    if (devclass_get_device(dc, 0) == NULL) {
        child = BUS_ADD_CHILD(parent, 0, "mydrv", -1);
    }
}

static int mydrv_probe(device_t dev) {
    printf("MSG2: The process inside the probe function.");
    mydrv_init();
    if (device_get_unit(dev) != 0)
        return (ENXIO);
    device_set_desc(dev, "FreeBSD Device Driver");
    return (0);
}

static int mydrv_attach(device_t dev) {
    struct mydrv_softc *sc;
    device_printf(dev, "MSG3: The process will make attachment.");
    sc = (struct mydrv_softc *) device_get_softc(dev);
    sc->dev = (device_t)make_dev(&mydrv_cdevsw, 0, UID_ROOT, GID_WHEEL, 0644, "mydrv_drv");
    return 0;
}

static int mydrv_detach(device_t dev) {
        struct mydrv_softc *sc;
    sc = (struct mydrv_softc *) device_get_softc(dev);
        destroy_dev((struct cdev*)(sc->dev));
    bus_generic_detach(dev);
    return 0;
}

static device_method_t mydrv_methods[] = {
    DEVMETHOD(device_identify,  mydrv_identify),
    DEVMETHOD(device_probe,     mydrv_probe),
    DEVMETHOD(device_attach,    mydrv_attach),
    DEVMETHOD(device_detach,    mydrv_detach),
    { 0, 0 }
};

static driver_t mydrv_driver = {
    "mydrv",
    mydrv_methods,
    sizeof(struct mydrv_softc),
};

DRIVER_MODULE(mydrv, ppbus, mydrv_driver, mydrv_devclass, 0, 0);
4

2 回答 2

0

我想printf工作正常,但我更喜欢使用device_printf它,因为它还打印设备名称,并且在查看日志或 dmesg 输出时会更容易。还要留下多个调试打印并检查系统上的日志文件。设备驱动程序的大多数日志都已登录/var/log/messages。但也要检查其他日志文件。你是在虚拟机上运行你的代码吗?/dev如果操作系统在虚拟机上运行,​​某些设备驱动程序不会显示其设备文件。您可能应该在实际硬件上运行您的操作系统以显示设备文件。据我所知,如果在 dmesg 中找不到对应的设备文件,则看不到输出/dev但正如我提到的,你可能对日志很幸运。最简单的调试方法当然是使用 printf 语句。除此之外,您可以使用在另一个系统上运行的 gdb 来调试内核。我不熟悉确切的过程,但我知道你可以做到这一点。去谷歌上查询。

于 2013-08-09T01:46:56.357 回答
0

如果您在控制台上看不到 printf 的输出,那么您的设备函数可能不会被调用。你能告诉我们你的模块的代码吗?你用过 DRIVER_MODULE() 还是 DEV_MODULE()?你用的是什么母线?

于 2013-08-13T13:53:15.310 回答