创建 I2C 设备驱动程序结构设置
我正在编写一个使用 I2C 与主机通信的设备驱动程序。
下面是我想学习和理解的代码。如果我对下面的代码的理解是错误的,请帮助我。 “//”是我自己的评论&我对代码的理解。
// declare there will be a member struct inside the class example_state. This member is pointing to i2c_client.
struct example_state {
struct i2c_client *client;
};
static int example_probe(struct i2c_client *client, const struct i2c_device_id *id{
// declare this to be a local struct inside the example_probe
struct example_state *state;
// get "struct device" to be pointed client's member name dev
// Question: is "struct device *dev" part of "struct i2c_client"?
// if "struct device *dev" imported from somewhere that why there is no need to allocate memory?
struct device *dev = &client->dev;
// allocate a memory space for "struct example_state"
// at this point "struct example_state" is still empty/NULL
// **Question:** but what is the relationship of this local "struct example_state"
// with the one declared before entering struct example_state function?
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
if (state == NULL) {
dev_err(dev, "failed to create our state\n");
return -ENOMEM;
}
// after memory allocated set the "struct i2c_client" point to "struct example_state"'s member namely "client".
state->client = client;
// set the our device I2C driver information to the host.
// Question: Where to we set our device driver data?
i2c_set_clientdata(client, state);
/* rest of the initialisation goes here. */
dev_info(dev, "example client created\n");
return 0;
}
static int __devexit example_remove(struct i2c_client *client){
// get the loaded value from host, i guess is like unregister
// my device driver information from the host when i exited.
struct example_state *state = i2c_get_clientdata(client);
kfree(state);
return 0;
}
static struct i2c_device_id example_idtable[] = {
{ "example", 0 },
{ }
};
I am writing a device driver which use I2C to communicate to host.
Below is the code I wanted to learn and understand. Do help me out If my understanding is wrong about the code below. "//" is my own comments & my understanding to the code.
// declare there will be a member struct inside the class example_state. This member is pointing to i2c_client.
struct example_state {
struct i2c_client *client;
};
static int example_probe(struct i2c_client *client, const struct i2c_device_id *id{
// declare this to be a local struct inside the example_probe
struct example_state *state;
// get "struct device" to be pointed client's member name dev
// Question: is "struct device *dev" part of "struct i2c_client"?
// if "struct device *dev" imported from somewhere that why there is no need to allocate memory?
struct device *dev = &client->dev;
// allocate a memory space for "struct example_state"
// at this point "struct example_state" is still empty/NULL
// **Question:** but what is the relationship of this local "struct example_state"
// with the one declared before entering struct example_state function?
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
if (state == NULL) {
dev_err(dev, "failed to create our state\n");
return -ENOMEM;
}
// after memory allocated set the "struct i2c_client" point to "struct example_state"'s member namely "client".
state->client = client;
// set the our device I2C driver information to the host.
// Question: Where to we set our device driver data?
i2c_set_clientdata(client, state);
/* rest of the initialisation goes here. */
dev_info(dev, "example client created\n");
return 0;
}
static int __devexit example_remove(struct i2c_client *client){
// get the loaded value from host, i guess is like unregister
// my device driver information from the host when i exited.
struct example_state *state = i2c_get_clientdata(client);
kfree(state);
return 0;
}
static struct i2c_device_id example_idtable[] = {
{ "example", 0 },
{ }
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我建议您不要研究 Linux 内核的 i2c 支持,而应该再看看 K&R 2 相反:
C 没有类。 Linux 内核的
sysfs
抽象引入了内核自己关于什么是“类”的想法 - 请参阅drivers/base/class.c
- 但它根本没有任何关系到 C++、Java、C# 或您熟悉的任何其他语言中的类。这将
state
声明为指向struct example_state
内存的指针。 (我通常会在这里使用“对象”这个词,但我不想抵消上一段中的“C 没有类”的言论。它是一块大小为或者大于保存 struct example_state 的所有成员所需的数量,并且编译器知道检查操作的类型一致性......)无论如何。 ,这行代码中只留出了足够的内存指针——不是结构本身。
此行中的 struct device *dev 为指针分配了足够的内存,并告诉编译器该指针仅指向 struct device 对象。
=&client->dev
查找client
参数以查找dev
成员并创建一个别名 以便在此例程中更轻松地使用。之前的 struct example_state { .. } 是一个类型声明。它仅向编译器指示存储在带有
struct example_state
标签的结构中的成员的名称、大小和类型。它不分配任何内存。这里的kzalloc()
调用确实分配内存,即我们的struct example_state
对象的大小,并且它请求正常的GFP_KERNEL< /code> 使用内存分配池。有关不同可用内存“池”的详细信息,请参阅
include/linux/gfp.h
。根据传递给内核内存分配器的标志,内存分配可能仅在内核被迫执行某种“垃圾收集”之后发生——将脏内存缓冲区写回磁盘,丢弃页面缓存、交换进程,甚至可能调用 OOM 内存杀手来分配内存。当内核绝对不能在此时休眠时,使用 GFP_ATOMIC 池——非常适合在持有自旋锁或在中断上下文中使用。虽然可以同时学习 C 语言和内核内部原理,但这是一个非常不允许犯错误的环境。在普通用户空间程序中跟踪流浪指针会使进程出现段错误,但在内核中跟踪流浪指针会使机器出现恐慌或损坏内存、文件系统等。
I'm going to suggest that instead of studying up on the Linux kernel's i2c support, you ought to take another look at K&R 2 instead:
C does not have classes. The Linux kernel's
sysfs
abstraction introduced the kernel's own idea of what a "class" is -- seedrivers/base/class.c
-- but it has no relationship at all to classes in C++, Java, C#, or any other language you're familiar with.This declares
state
to be a pointer to astruct example_state
piece of memory. (I'd normally use the word object here, but I don't want to counteract the "C does not have classes" speech from the previous paragraph. It's a piece of memory that is as large as or larger than the amount necessary to hold all the members of thestruct example_state
, and the compiler knows to check operations for type consistency. Maybe I should have just said "object"...)In any event, there is only enough memory set aside in this line of code for a pointer -- not the structure itself.
The
struct device *dev
in this line allocates enough memory for a pointer and tells the compiler that the pointer will only point tostruct device
objects. The=&client->dev
looks into theclient
parameter to find thedev
member and makes an alias for easier use within this routine.The
struct example_state { .. }
from earlier was a type declaration. It only instructed the compiler about the names, sizes, and types, of members stored in structs with the tagstruct example_state
. It does not allocate any memory. Thekzalloc()
call here does allocate memory, the size of ourstruct example_state
objects, and it requests that the normalGFP_KERNEL
memory allocation pool be used. Seeinclude/linux/gfp.h
for details on the different "pools" of memory available. Depending upon the flags passed to the kernel's memory allocator, the memory allocation might happen only after the kernel has been forced to perform a "garbage collection" of sorts -- writing dirty memory buffers back to disk, dropping page caches, swapping processes, maybe even invoking the OOM memory killer to allocate memory. TheGFP_ATOMIC
pool is used when the kernel absolutely must not sleep at that point -- excellent for use when spinlocks are held or in interrupt context.While it is possible to learn C and kernel internals simultaneously, it is a very unforgiving environment to make mistakes. Following a stray pointer in a normal userspace program segfaults the process but following a stray pointer in the kernel panics the machine or corrupts memory, filesystems, etc.