2012-10-16 107 views
1

我已经开始学习Linux驱动程序,但是我觉得它有点困难。Linux设备驱动程序,程序启动的地方?

我一直在研究i2c驱动程序,我对驱动程序的入口点感到非常困惑。驱动程序是否从MOUDULE_INIT()宏开始?

我还想知道如何知道驱动程序如何运行的过程。我拿到了这本书,Linux设备驱动程序,但我仍然很困惑。你可以帮帮我吗?非常感谢。

我以i2c驱动程序为例。其中只有很多功能,我只是想知道如何在i2c驱动程序中协调功能的关系。

回答

-2

“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); 

的最高最新的教程,写得很好,是“Linux Device Drivers Series

+0

thx很多。有帮助 – Alexander

+3

这是“接受”的答案?这只是一个评论,一个复制粘贴和一个链接。你(@亚历山大)提出4个问题,而没有人提出或回答。 – sawdust

+1

@Sawdust我猜OP对于简洁和链接感到满意;对于他的问题没有具体的答案,他并不真正困扰。 – TheCodeArtist

1

这可能有助于停止将设备驱动程序作为一个程序来思考。他们完全不同。一个程序有一个特定的起点,做一些事情,并有一个或多个相当明确的定义(呃,他们应该,无论如何)退出点。当第一次加载时(例如MODULE_INIT()等),驱动程序有一些要做的事情,并且可能会或可能不会再做任何事情(您可以强制加载驱动程序用于系统实际没有的硬件),并且可能有如果驱动程序被卸载,需要完成一些工作。除此之外,驱动程序通常会提供一些用户登陆应用程序可以访问的特定入口点(系统调用,ioctl等)以请求驱动程序执行某些操作。可怕的比喻,但想象一种类似于汽车的程序 - 你进入,启动它,开车到某处,然后出去。司机更像是一台自动售货机 - 你插上电源并确保它已经存货了,但是人们偶尔会来,并按下按钮使它做某事。

+0

非常感谢你 – Alexander

5

设备驱动程序是不是“计划”,有一个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; 
}; 

对于字符设备,所述预计驱动程序将提供它可以执行的操作列表,通过声明其功能用于以下操作(来自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; 
}; 

司机,特别是字符驱动,不必须支持列出的每项操作。请注意,有些宏通过命名结构条目来促进这些结构的编码。

驱动程序是否从MOUDLUE_INIT()宏开始?在MODULE_INIT()指定

驾驶员的的init()例程将在引导期间被调用(当静态链接中),或者当被动态加载的模块。驾驶员通过其操作的结构与设备的子系统,当其的init()期间它寄存器本身。

这些设备驱动程序入口点,例如打开()读(),当用户应用程序调用一个C库调用(在用户空间)通常执行和切换到内核空间后。请注意,您正在寻找的I2C驱动是所使用的设备的总线一个platform driver,其通过EXPORT_SYMBOL()曝光功能会被其他司机被调用。

只有驱动程序的init()程序中指定的MODULE_INIT()保证被调用。驾驶员在MODULE_EXIT()指定出口()例程将只如果/当所述模块被动态地执行卸载。驱动程序的例程将以未知的顺序异步调用(就像它的中断服务程序一样)。希望用户程序在发出read()ioctl()操作之前调用open(),并以合理的方式调用其他操作。一个写得很好且健壮的驱动程序应该能够适应任何操作顺序或操作顺序,并且产生合理的结果以确保系统的完整性。

0

其实你正在服用约(I2C)平台(母语)驱动程序首先你需要了解的平台驱动程序如何MOUDULE_INIT()接到电话与其他可加载模块。

/* 
* 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.*/ 

和I2C驱动,你可以参考这个链接http://www.linuxjournal.com/article/7136http://www.embedded-bits.co.uk/2009/i2c-in-the-2632-linux-kernel/

0

开始一个内核模块是由初始化函数,它主要是针对与宏观__init刚盈函数名的开始。

__init宏向linux内核表明,以下函数是一个初始化函数,一旦初始化函数的代码被执行,用于这个初始化函数的资源将被释放。

还有其他的marcos,用于检测初始化和释放函数,名为module_init()和module_exit()[如上所述]。

如果设备驱动程序的目标是在运行时用作可加载和可移除的内核模块,则使用这两个宏。使用insmod或rmmod命令]

0

简而言之:从.probe开始,一旦执行insmod,就会一路开始init。这也会将驱动程序注册到驱动程序子系统,并启动init。 每次从用户应用程序调用驱动程序功能时,都会使用回调调用功能。