设备驱动程序不是具有起点和出点的main {}的“程序”。它更像是API或库或例程集合。在这种情况下,它是由MODULE_INIT(),MODULE_EXIT(),也许是EXPORT_SYMBOL()声明的一组入口点,以及列出操作入口点的结构。
对于块设备,驱动程序应通过为(来自include/linux/blkdev.h)的那些操作声明其功能来提供它可以执行的操作列表:
struct block_device_operations {
int (*open) ();
int (*release) ();
int (*ioctl) ();
int (*compat_ioctl) ();
int (*direct_access) ();
unsigned int (*check_events) ();
/* ->media_changed() is DEPRECATED, use ->check_events() instead */
int (*media_changed) ();
void (*unlock_native_capacity) ();
int (*revalidate_disk) ();
int (*getgeo)();
/* this callback is with swap_lock and sometimes page table lock held */
void (*swap_slot_free_notify) ();
struct module *owner;
};对于char设备,驱动程序应通过为(来自include/linux/fs.h)的那些操作声明其功能来提供它可以执行的操作列表:
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)();
};对于平台设备,驱动程序应通过为(来自include/linux/platform_device.h)的那些操作声明其功能来提供它可以执行的操作列表:
struct platform_driver {
int (*probe)();
int (*remove)();
void (*shutdown)();
int (*suspend)();
int (*resume)();
struct device_driver driver;
const struct platform_device_id *id_table;
};驱动程序,尤其是char驱动程序,不必支持列出的每个操作。请注意,有些宏通过命名结构条目来促进这些结构的编码。
Does the driver program starts at the MOUDLUE_INIT() macro?
MODULE_INIT()中指定的驱动程序的init()例程将在引导期间(静态链接时)或模块动态加载时调用。当驱动程序在init()期间注册自身时,驱动程序将其操作结构传递给设备的子系统。
这些设备驱动程序入口点,例如open()或read()通常在用户app调用C库调用(在用户空间中)和切换到内核空间后执行。请注意,您正在查看的i2c驱动程序是叶子设备使用的总线的platform driver,其他驱动程序将调用由EXPORT_SYMBOL()公开的其功能。
保证只调用MODULE_INIT()中指定的驱动程序的init()例程。只有在/动态卸载模块时,才会执行MODULE_EXIT()中指定的驱动程序的exit()例程。驱动程序的op例程将以未知顺序异步调用(就像它的中断服务例程一样)。希望用户程序在发出read()或ioctl()操作之前调用open(),并以合理的方式调用其他操作。一个编写良好且功能强大的驱动程序应该适应任何顺序或操作顺序,并产生合理的结果以确保系统完整性。