日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux驱动私有数据,linux驱动开发之字符设备--私有数据和container_of

發布時間:2023/12/19 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux驱动私有数据,linux驱动开发之字符设备--私有数据和container_of 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

驅動開發中通常為設備定義一個設備相關的設備結構體,其包含該設備的cdev 、私有數據、信號量、irq等這些信息。

驅動開發中通常將文件的私有數據private_data指向設備結構體,在read()、write()、ioctl()等函數通過 private_data 訪問數據 設備結構體。

container_of() 是一個比較常用的宏,其作用為通過結構體成員的指針找到對應結構體的指針。

通過分析 akm8975.c 這個文件進行分析

分析

自定義的結構體 akm8975_data ,包含了 i2c_client 、work_struct等信息。

struct akm8975_data {

struct i2c_client *this_client;

struct akm8975_platform_data *pdata;

struct input_dev *input_dev;

struct work_struct work;

struct mutex flags_lock;

#ifdef CONFIG_HAS_EARLYSUSPEND

struct early_suspend early_suspend;

#endif

定義一個全局的變量 akmd_data

/*

* Because misc devices can not carry a pointer from driver register to

* open, we keep this global. This limits the driver to a single instance.

*/

struct akm8975_data *akmd_data;

自定義的設備結構體的初始化:

int akm8975_probe(struct i2c_client *client,

const struct i2c_device_id *devid){

...

struct akm8975_data *akm; //申請一個局部的結構體指針

akm = kzalloc(sizeof(struct akm8975_data), GFP_KERNEL); //初始這個指針

akmd_data = akm; //復制給全局的變量

}

將自定義的設備結構體賦值給 file的private_data

static int akm_aot_open(struct inode *inode, struct file *file){

...

file->private_data = akmd_data;

}

通過file取得private_data

tatic int akm_aot_ioctl(struct inode *inode, struct file *file,

unsigned int cmd, unsigned long arg)

{

void __user *argp = (void __user *) arg;

short flag;

struct akm8975_data *akm = file->private_data;

自定義的設備結構體,通常有以下操作

定義一個全局的變量

在probe 或者入口函數中初始化 全局變量

在 file_operation open 中,將全局變量賦值給file的private_data

在read() 、wriete、ioctl()的操作中,通過file取中private_data 進行操作

在定義的設備結構體中 一項 工作隊列。 這個工作隊列 是如何和 container_of聯系起來的呢? 先看下代碼中的相關內容。

初始化工作隊列

int akm8975_probe(struct i2c_client *client,

const struct i2c_device_id *devid){

...

INIT_WORK(&akm->work, akm_work_func);

}

工隊隊列

static void akm_work_func(struct work_struct *work)

{

struct akm8975_data *akm =

container_of(work, struct akm8975_data, work); //利用container_of,獲得work指針對于的設備結構體指針 akm

FUNCDBG("called");

//通過獲得的akm指針,從結構體中,取出成員來執行相應的操作。

enable_irq(akm->this_client->irq);

}

調度 工作隊列

static irqreturn_t akm8975_interrupt(int irq, void *dev_id)

{

struct akm8975_data *akm = dev_id;

FUNCDBG("called");

disable_irq_nosync(akm->this_client->irq);

schedule_work(&akm->work);

return IRQ_HANDLED;

}

通過定義一個設備結構體,可以將設備相關的操作、信息封裝在一起,后邊可以使用 container_of 得到這個結構體。將數據傳遞給private_data 更加規范和調理。

container_of

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

offsetof 通過將 0 地址,強制轉為為TYPE類型的指針,然后取它的成員 NUMBER , 在轉為size_t 類型。即得到 NUMBER 在這個TYPE的位置。

/**

* container_of - cast a member of a structure out to the containing structure

* @ptr: the pointer to the member.

* @type: the type of the container struct this is embedded in.

* @member: the name of the member within the struct.

*

*/

#define container_of(ptr, type, member) ({ \

const typeof(((type *)0)->member) * __mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); }) #endif

參考文獻

總結

以上是生活随笔為你收集整理的linux驱动私有数据,linux驱动开发之字符设备--私有数据和container_of的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。