あなたmiscdeviceが初めてオープンされているときに、miscdeviceフレームワークは、(misc_open()機能ともcomment to misc_register()機能を参照してください)struct miscdevice
にfile->private_data
を設定します。これに依存して、container_of()
マクロを使用して、カスタム構造を得るために、ファイル操作でfile->private_data
を使用することができます。もちろん、カスタム構造にはstruct miscdevice
が含まれている必要があります。これを行うためのきれいで一般的に使用される方法はto_*()
というヘルパー関数を作成することです。これはfile
ポインタによってカスタム構造体を取り出して返します。したがって、カスタム構造体my_struct
を呼び出した場合は、そのヘルパー関数をto_my_struct()
と呼びます。
また、プラットフォームドライバを作成する場合は、dev_set_drvdata()
の代わりにplatform_set_drvdata()
を使用できます。これはあなたのプラットフォームドライバの機能remove()
でカスタム構造を得るために必要です。
$ git grep -l --all-match -e 'misc_register(' -e 'platform_device' -e 'file->private_data' -- drivers/
:ところで
struct my_struct {
struct platform_device *pdev;
struct miscdevice mdev;
};
static inline struct my_struct *to_my_struct(struct file *file)
{
struct miscdevice *miscdev = file->private_data;
return container_of(miscdev, struct my_struct, mdev);
}
static ssize_t my_read(struct file *file, char __user *buf, size_t count,
loff_t *pos)
{
struct my_struct *my = to_my_struct(file);
return simple_read_from_buffer(buf, count, pos, "my text", 7);
}
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.read = my_read,
};
static int my_probe(struct platform_device *pdev)
{
struct my_struct *my;
int ret;
my = devm_kzalloc(&pdev->dev, sizeof(*my), GFP_KERNEL);
if (!my)
return -ENOMEM;
platform_set_drvdata(pdev, my);
my->pdev = pdev;
my->mdev.minor = MISC_DYNAMIC_MINOR;
my->mdev.name = "my";
my->mdev.fops = &my_fops;
my->mdev.parent = NULL;
ret = misc_register(&my->mdev);
if (ret) {
dev_err(&pdev->dev, "Failed to register miscdev\n");
return ret;
}
dev_info(&pdev->dev, "Registered\n");
return 0;
}
static int my_remove(struct platform_device *pdev)
{
struct my_struct *my = platform_get_drvdata(pdev);
misc_deregister(&my->mdev);
dev_info(&pdev->dev, "Unregistered\n");
return 0;
}
、あなたはこのように、単にキーワードを使用して、カーネルコードの例を探すことができます:ここで
はすべてが上に説明のための例です。