创建 I2C 设备驱动程序结构设置

发布于 2024-12-16 02:48:18 字数 1918 浏览 2 评论 0原文

我正在编写一个使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情定在深秋 2024-12-23 02:48:18

我建议您不要研究 Linux 内核的 i2c 支持,而应该再看看 K&R 2 相反:

// 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; 
};

C 没有类。 Linux 内核的 sysfs 抽象引入了内核自己关于什么是“类”的想法 - 请参阅 drivers/base/class.c - 但它根本没有任何关系到 C++、Java、C# 或您熟悉的任何其他语言中的类。

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;

这将 state 声明为指向 struct example_state 内存的指针。 (我通常会在这里使用“对象”这个词,但我不想抵消上一段中的“C 没有类”的言论。它是一块大小为或者大于保存 struct example_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;

此行中的 struct device *dev 为指针分配了足够的内存,并告诉编译器该指针仅指向 struct device 对象。 =&client->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;
}

之前的 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:

// 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; 
};

C does not have classes. The Linux kernel's sysfs abstraction introduced the kernel's own idea of what a "class" is -- see drivers/base/class.c -- but it has no relationship at all to classes in C++, Java, C#, or any other language you're familiar with.

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;

This declares state to be a pointer to a struct 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 the struct 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.

// 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;

The struct device *dev in this line allocates enough memory for a pointer and tells the compiler that the pointer will only point to struct device objects. The =&client->dev looks into the client parameter to find the dev member and makes an alias for easier use within this routine.

// 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;
}

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 tag struct example_state. It does not allocate any memory. The kzalloc() call here does allocate memory, the size of our struct example_state objects, and it requests that the normal GFP_KERNEL memory allocation pool be used. See include/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. The GFP_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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文