天天看點

C語言函數指針和結構體怎麼進階玩?Linux核心驅動架構代碼告訴你

我将結合具體的Linux核心驅動架構代碼來展示Linux核心如何使用結構體和函數指針。

以下是一個簡化的示例代碼,展示了Linux核心驅動中使用結構體和函數指針的進階用法:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>

// 定義裝置結構體
struct my_device_data {
    int foo;
    int bar;
};

// 定義操作函數結構體
struct my_device_ops {
    int (*open)(struct my_device_data *data);
    void (*close)(struct my_device_data *data);
};

// 操作函數實作
static int my_device_open(struct my_device_data *data)
{
    printk(KERN_INFO "Device opened (foo=%d, bar=%d)\n", data->foo, 
           data->bar);
    return 0;
}

static void my_device_close(struct my_device_data *data)
{
    printk(KERN_INFO "Device closed (foo=%d, bar=%d)\n", data->foo,
           data->bar);
}

// 平台裝置驅動實作
static int my_device_probe(struct platform_device *pdev)
{
    struct my_device_data *data;
    struct my_device_ops *ops;

    // 擷取裝置資料
    data = devm_kzalloc(&pdev->dev, sizeof(struct my_device_data), 
                        GFP_KERNEL);
    if (!data)
        return -ENOMEM;

    data->foo = 42;
    data->bar = 66;

    // 擷取操作函數結構體
    ops = (struct my_device_ops *)pdev->dev.platform_data;

    // 調用操作函數
    if (ops && ops->open)
        ops->open(data);

    platform_set_drvdata(pdev, data);

    return 0;
}

static int my_device_remove(struct platform_device *pdev)
{
    struct my_device_data *data = platform_get_drvdata(pdev);
    struct my_device_ops *ops;

    ops = (struct my_device_ops *)pdev->dev.platform_data;

    // 調用操作函數
    if (ops && ops->close)
        ops->close(data);

    return 0;
}

// 平台裝置結構體
static struct platform_device my_device = {
    .name = "my_device",
    .id = -1,
    .dev = {
        .platform_data = &my_device_ops,
    },
};

// 操作函數結構體執行個體化
static struct my_device_ops my_device_ops = {
    .open = my_device_open,
    .close = my_device_close,
};

// 初始化和退出函數
static int __init my_driver_init(void)
{
    int ret;

    ret = platform_device_register(&my_device);
    if (ret) {
        pr_err("Failed to register platform device\n");
        return ret;
    }

    return 0;
}

static void __exit my_driver_exit(void)
{
    platform_device_unregister(&my_device);
}

module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("My Device Driver");
MODULE_LICENSE("GPL");
           

在上面的示例代碼中,我們定義了一個名為my_device_data的裝置結構體,用于儲存設備的資料。接下來,我們定義了一個名為my_device_ops的操作函數結構體,其中包含了裝置操作的函數指針。

在平台裝置驅動的實作中,我們在my_device_probe函數中,通過pdev->dev.platform_data擷取了操作函數結構體的指針,并将其指派給ops。然後,我們可以使用ops->open函數指針調用裝置的打開操作。

類似地,在my_device_remove函數中,我們再次使用pdev->dev.platform_data擷取了操作函數結構體的指針,并将其指派給ops。然後,我們可以使用ops->close函數指針調用裝置的關閉操作。

這種使用結構體和函數指針的方式使得裝置的操作函數可以通過結構體中的函數指針進行動态調用,進而實作了高度的靈活性和可擴充性。

總結一下,Linux核心驅動中使用結構體和函數指針的進階用法可以通過定義包含函數指針的操作函數結構體,在驅動中使用該結構體來調用裝置的操作函數。這種方式使得驅動的行為可以在運作時動态配置,增加了驅動的靈活性和可擴充性。

請注意,上述代碼隻是一個簡化的示例,實際的驅動程式會更加複雜,并涉及到更多的裝置操作和功能。這裡提供的代碼僅用于示範結構體和函數指針的進階用法,并不涵蓋所有的細節和實作。在實際開發中,需要根據具體的裝置和需求進行适當的修改和擴充。

繼續閱讀