Linux kernel Linux设备驱动程序,程序从哪里开始?
我已经开始学习Linux驱动程序,但我发现有点难 我一直在研究i2c驱动程序,对于驱动程序的入口点我感到很困惑。驱动程序是否从Linux kernel Linux设备驱动程序,程序从哪里开始?,linux-kernel,linux-device-driver,Linux Kernel,Linux Device Driver,我已经开始学习Linux驱动程序,但我发现有点难 我一直在研究i2c驱动程序,对于驱动程序的入口点我感到很困惑。驱动程序是否从MOUDULE\u INIT()宏启动 我还想知道如何知道驱动程序的运行过程。我拿到了《Linux设备驱动程序》这本书,但我还是很困惑。你能帮我吗?非常感谢 我将以i2c驱动程序为例。它的功能太多了,我只想知道如何才能得到i2c驱动程序中功能的协调关系?这可能有助于停止将设备驱动程序视为一个程序。他们完全不同。一个程序有一个特定的起点,做一些事情,并且有一个或多个相当好的
MOUDULE\u INIT()宏启动
我还想知道如何知道驱动程序的运行过程。我拿到了《Linux设备驱动程序》这本书,但我还是很困惑。你能帮我吗?非常感谢
我将以i2c驱动程序为例。它的功能太多了,我只想知道如何才能得到i2c驱动程序中功能的协调关系?这可能有助于停止将设备驱动程序视为一个程序。他们完全不同。一个程序有一个特定的起点,做一些事情,并且有一个或多个相当好的定义(无论如何,它们应该)的退出点。驱动程序在第一次加载时有一些事情要做(例如,MODULE_INIT()
和其他事情),并且可能会或者永远不会再做任何事情(您可以强制加载系统实际没有的硬件的驱动程序),如果卸载驱动程序,可能需要做一些事情。除此之外,驱动程序通常提供一些特定的入口点(系统调用、IOCTL等),用户陆地应用程序可以访问这些入口点来请求驱动程序执行某些操作
可怕的类比,但想想一个有点像汽车的程序——你进去,启动它,开车到某个地方,然后下车。驱动程序更像是一台自动售货机——你把它插上电源,确保里面有存货,但人们只是偶尔来按一下按钮,让它做点什么。这可能有助于停止将设备驱动程序视为一个程序的想法。他们完全不同。一个程序有一个特定的起点,做一些事情,并且有一个或多个相当好的定义(无论如何,它们应该)的退出点。驱动程序在第一次加载时有一些事情要做(例如,MODULE_INIT()
和其他事情),并且可能会或者永远不会再做任何事情(您可以强制加载系统实际没有的硬件的驱动程序),如果卸载驱动程序,可能需要做一些事情。除此之外,驱动程序通常提供一些特定的入口点(系统调用、IOCTL等),用户陆地应用程序可以访问这些入口点来请求驱动程序执行某些操作
可怕的类比,但想想一个有点像汽车的程序——你进去,启动它,开车到某个地方,然后下车。驱动程序更像是一台自动售货机——你把它插上电源,确保里面有存货,但人们只是偶尔来按一下按钮,让它做点什么。《Linux设备驱动程序》是一本好书,但它已经过时了
基本示例:
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Name and e-mail");
MODULE_DESCRIPTION("my_first_driver");
static int __init insert_mod(void)
{
printk(KERN_INFO "Module constructor");
return 0;
}
static void __exit remove_mod(void)
{
printk(KERN_INFO "Module destructor");
}
module_init(insert_mod);
module_exit(remove_mod);
#包括
#包括
#包括
模块许可证(“GPL”);
模块_作者(“姓名和电子邮件”);
模块描述(“我的第一个驱动程序”);
静态整数初始化插入模块(无效)
{
printk(KERN_INFO“模块构造函数”);
返回0;
}
静态无效\退出删除\修改(无效)
{
printk(KERN_INFO“模块析构函数”);
}
模块初始化(插入模块);
模块退出(移除模块);
一个最新的教程,写得很好,是““Linux设备驱动程序”是一本好书,但它已经过时了
基本示例:
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Name and e-mail");
MODULE_DESCRIPTION("my_first_driver");
static int __init insert_mod(void)
{
printk(KERN_INFO "Module constructor");
return 0;
}
static void __exit remove_mod(void)
{
printk(KERN_INFO "Module destructor");
}
module_init(insert_mod);
module_exit(remove_mod);
#包括
#包括
#包括
模块许可证(“GPL”);
模块_作者(“姓名和电子邮件”);
模块描述(“我的第一个驱动程序”);
静态整数初始化插入模块(无效)
{
printk(KERN_INFO“模块构造函数”);
返回0;
}
静态无效\退出删除\修改(无效)
{
printk(KERN_INFO“模块析构函数”);
}
模块初始化(插入模块);
模块退出(移除模块);
一个最新的教程,写得很好,是“一个设备驱动程序不是一个“程序”,它有一个带有起始点和退出点的main{}
。它更像是一个API、一个库或一组例程。在本例中,它是由MODULE\u INIT()
、MODULE\u EXIT()
、也许是EXPORT\u SYMBOL()
和列出操作入口点的结构声明的一组入口点
对于块设备,希望驱动程序通过在(frominclude/linux/blkdev.h
)中声明其操作功能来提供可执行的操作列表:
对于char设备,驱动程序应通过在(frominclude/linux/fs.h
)中声明其操作功能来提供可执行的操作列表:
对于平台设备,希望驱动程序通过在(frominclude/linux/platform\u device.h
)中声明其操作功能来提供可执行的操作列表:
驱动程序,尤其是char驱动程序,不必支持列出的每个操作。请注意,有一些宏可以通过命名结构条目来简化这些结构的编码
驱动程序是否从MOUDLUE_INIT()宏开始
在引导期间(静态链接时)或模块动态加载时,将调用模块中指定的驱动程序init()例程。驱动程序在其init()期间注册自身时,会将其操作结构传递给设备的子系统
这些设备驱动程序入口点,例如open()或read(),通常在用户应用程序调用C库调用(在用户空间中)和切换到内核空间后执行。请注意,您正在查看的i2c驱动程序是一个用于leaf设备使用的总线的驱动程序,其由EXPORT\u SYMBOL()
公开的函数将被其他驱动程序调用
只有MODULE\u init()
中指定的驱动程序的init()例程才能保证被调用。只有在动态卸载模块时,才会执行模块退出()中指定的驱动程序退出()例程。驱动程序的操作例程将被异步调用(就像它的中断一样)
struct file_operations {
struct module *owner;
loff_t (*llseek) ();
ssize_t (*read) ();
ssize_t (*write) ();
ssize_t (*aio_read) ();
ssize_t (*aio_write) ();
int (*readdir) ();
unsigned int (*poll) ();
long (*unlocked_ioctl) ();
long (*compat_ioctl) ();
int (*mmap) ();
int (*open) ();
int (*flush) ();
int (*release) ();
int (*fsync) ();
int (*aio_fsync) ();
int (*fasync) ();
int (*lock) ();
ssize_t (*sendpage) ();
unsigned long (*get_unmapped_area)();
int (*check_flags)();
int (*flock) ();
ssize_t (*splice_write)();
ssize_t (*splice_read)();
int (*setlease)();
long (*fallocate)();
};
struct platform_driver {
int (*probe)();
int (*remove)();
void (*shutdown)();
int (*suspend)();
int (*resume)();
struct device_driver driver;
const struct platform_device_id *id_table;
};
/*
* module_init() - driver initialization entry point
* @x: function to be run at kernel boot time or module insertion
* module_init() will either be called during do_initcalls() (if
* builtin) or at module insertion time (if a module). There can only
* be one per module.*/