【问题标题】:Problems with netdev_alloc and netdev_priv in kernel network driver内核网络驱动程序中的 netdev_alloc 和 netdev_priv 问题
【发布时间】:2014-03-07 23:20:40
【问题描述】:

我有一个自定义的 FPGA 逻辑,我已经为它实现了一个功能性的 char 驱动程序,我现在正试图让它作为一个网络驱动程序工作。我将尽我所能使用 LDD book、snull 代码和 loopback.c、dummy.c 以及内核中的其他驱动程序作为示例。

我下面的代码(显然是从较大的文件中提取的)是我目前拥有的网络驱动程序代码;我可以成功地 insmod,并且“ifconfigoptical0”显示我的 MTU 和标志是正确的,所以我知道至少它正在被注册。

现在我正在尝试实现 struct net_device 的私有字段 (void* priv) 来存储统计信息和其他内容,这会导致段错误。到目前为止的代码如下:

struct serdes_device {
    struct serdes_regs __iomem *regs;
    struct serdes_dma *tx_dma,
                      *rx_dma;

    struct device *dev;
    struct net_device *netdev;
    struct resource serdes_res; 
    struct cdev cdev;
    int major, minor;

    int tx_kbps;
    int rx_kbps;
};  

struct optical_priv {
    struct serdes_device *serdes_dev;
    struct net_device_stats stats;
};

static const struct net_device_ops optical_netdev_ops = {
    .ndo_get_stats = optical_stats,
    .ndo_start_xmit = optical_xmit,
    /* and so on, not including the ops functions for brevity */
};

void optical_setup(struct net_device *dev)
{
    dev->netdev_ops = &optical_netdev_ops;
    dev->destructor = free_netdev;

    dev->tx_queue_len = 1;
    dev->type = ARPHRD_NONE;
    dev->hard_header_len = SERDES_FRAME_HEADER_LENGTH;
    dev->mtu = SERDES_FRAME_TOTAL_LENGTH;
    dev->addr_len = 0;

    dev->flags &= ~IFF_BROADCAST;
    /* more flags & features cut */
}

static int optical_init(struct net_device *netdev)
{
    int err;
    struct optical_priv *priv;

    netdev = alloc_netdev(sizeof(struct optical_priv), "optical%d", optical_setup);
    if (!netdev)
        return -ENOMEM;

    err = register_netdev(netdev);
    if (err < 0)
        goto err;

    priv = netdev_priv(netdev);
    printk(KERN_WARNING "priv is at address 0x%p\n", priv);

    return 0;

err:
    free_netdev(netdev);
    return err;
}

static int serdes_of_probe(struct platform_device *op)
{
    struct serdes_device *serdes_dev;
    struct optical_priv *priv;
    int err = 0;

    serdes_dev = kzalloc(sizeof(struct serdes_device), GFP_KERNEL);

    /* A bunch of unrelated openfirmware & cdev code removed. */

    err = optical_init(serdes_dev->netdev);
    if (err < 0)
        dev_err(serdes_dev->dev, "Error %d initing optical link\n", err);

priv = netdev_priv(serdes_dev->netdev);
    if (!priv)
        dev_err(serdes_dev->dev, "priv is null... \n");

    dev_info(serdes_dev->dev, "priv is at 0x%p\n", priv);
    dev_info(&op->dev, "Done probing.\n");

    return 0;

out_free_serdes:
    kfree(serdes_dev);

out_return:
    return err;
}

据我所知,我正在为我的 serdes 设备分配空间并初始化我的 serdes 设备(我知道它可以用作 char 驱动程序)。然后我调用optical_init 来分配、注册和配置serdes_dev->netdev。 alloc_netdev 也应该为 (void *)priv 字段分配空间,这就是传入 sizeof(structoptical_priv) 的原因。

其中两个打印语句的 insmod 之后的输出如下所示:

priv is at address 0xdd2de500
priv is at 0x00000500
Done probing.

并且显然在此之后尝试以任何方式访问 priv 会导致段错误。我认为我的困惑是为什么 netdev_priv() 在从两个不同的函数调用时返回两个不同的值——不应该在 alloc_netdev 之后的任何时候分配和更正吗?

e:我想我也在寻找太多驱动程序中的示例,来自太多时代,沉浸在过去的硬件和内核 API 的历史中......如果有人对我有很好的基本驱动程序推荐首先,我非常乐意阅读代码来学习。

【问题讨论】:

    标签: c linux-kernel network-programming linux-device-driver


    【解决方案1】:

    我认为问题出在这里:

    err = optical_init(serdes_dev->netdev);
    

    您将无效指针传递给 netdev 结构。然后在optical_init() 中更改指针的本地值:

    netdev = alloc_netdev(sizeof(struct optical_priv), "optical%d", optical_setup);
    

    现在您有一个指向struct net_device 的有效指针。但是该指针值不适用于serdes_dev-&gt;netdev 变量,而仅适用于optical_init() 中的本地变量。因此,指向priv 的指针也是无效的。这是一个显示问题的小例子:

    #include <stdio.h>
    #include <stdlib.h>
    
    struct test {
        int first;
        int *second;
    };
    
    void allocate_memory(int *ptr)
    {
        ptr = malloc(10);
        printf("while allocating %p\n", ptr);
    }
    
    int main(void) {
        struct test *p1;
    
        p1= malloc(sizeof(struct test));
    
        printf("before %p\n", p1->second);
        allocate_memory(p1->second);
        printf("after %p\n", p1->second);
    
        free(p1);
        free(p2);
    
        return EXIT_SUCCESS;
     }
    

    输出是:

    before (nil)
    while allocating 0x23ee030
    after (nil)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-20
      • 2021-12-01
      • 2023-03-15
      相关资源
      最近更新 更多