Linux Device Driver Program, where the program sta

2019-01-09 16:52发布

问题:

I've started to learn Linux driver programs, but I'm finding it a little difficult.

I've been studying the i2c driver, and I got quite confused regarding the entry-point of the driver program. Does the driver program start at the MOUDULE_INIT() macro?

And I'd also like to know how I can know the process of how the driver program runs. I got the book, Linux Device Driver, but I'm still quite confused. Could you help me? Thanks a lot.

I'll take the i2c driver as an example. There are just so many functions in it, I just wanna know how I can get coordinating relation of the functions in the i2c drivers?

回答1:

"Linux Device Driver" is a good book but it's old!

Basic example:

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

An up-to-date tutorial, really well written, is "Linux Device Drivers Series"



回答2:

A device driver is not a "program" that has a main {} with a start point and exit point. It's more like an API or a library or a collection of routines. In this case, it's a set of entry points declared by MODULE_INIT(), MODULE_EXIT(), perhaps EXPORT_SYMBOL() and structures that list entry points for operations.

For block devices, the driver is expected to provide the list of operations it can perform by declaring its functions for those operations in (from 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;
};

For char devices, the driver is expected to provide the list of operations it can perform by declaring its functions for those operations in (from 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)();
};

For platform devices, the driver is expected to provide the list of operations it can perform by declaring its functions for those operations in (from 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;
};

The driver, especially char drivers, does not have to support every operation listed. Note that there are macros to facilitate the coding of these structures by naming the structure entries.

Does the driver program starts at the MOUDLUE_INIT() macro?

The driver's init() routine specified in MODULE_INIT() will be called during boot (when statically linked in) or when the module is dynamically loaded. The driver passes its structure of operations to the device's subsystem when it registers itself during its init().

These device driver entry points, e.g. open() or read(), are typically executed when the user app invokes a C library call (in user space) and after a switch to kernel space. Note that the i2c driver you're looking at is a platform driver for a bus that is used by leaf devices, and its functions exposed by EXPORT_SYMBOL() would be called by other drivers.

Only the driver's init() routine specified in MODULE_INIT() is guaranteed to be called. The driver's exit() routine specified in MODULE_EXIT() would only be executed if/when the module is dynamically unloaded. The driver's op routines will be called asynchronously (just like its interrupt service routine) in unknown order. Hopefully user programs will invoke an open() before issuing a read() or an ioctl() operation, and invoke other operations in a sensible fashion. A well-written and robust driver should accommodate any order or sequence of operations, and produce sane results to ensure system integrity.



回答3:

It would probably help to stop thinking of a device driver as a program. They're completely different. A program has a specific starting point, does some stuff, and has one or more fairly well defined (well, they should, anyway) exit point. Drivers have some stuff to do when the first get loaded (e.g. MODULE_INIT() and other stuff), and may or may not ever do anything ever again (you can forcibly load a driver for hardware your system doesn't actually have), and may have some stuff that needs to be done if the driver is ever unloaded. Aside from that, a driver generally provides some specific entry points (system calls, ioctls, etc.) that user-land applications can access to request the driver to do something.

Horrible analogy, but think of a program kind of like a car - you get in, start it up, drive somewhere, and get out. A driver is more like a vending machine - you plug it in and make sure it's stocked, but then people just come along occasionaly and push buttons to make it do something.



回答4:

Actually you are taking about (I2C) platform (Native)driver first you need to understand how MOUDULE_INIT() of platform driver got called versus other loadable modules.

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

and for i2c driver you can refer this link http://www.linuxjournal.com/article/7136 and http://www.embedded-bits.co.uk/2009/i2c-in-the-2632-linux-kernel/



回答5:

Begin of a kernel module is starting from initialization function, which mainly addressed with macro __init just infront of the function name.

The __init macro indicate to linux kernel that the following function is an initialization function and the resource that will use for this initialization function will be free once the code of initialization function is executed.

There are other marcos, used for detect initialization and release function, named module_init() and module_exit() [as described above].

These two macro are used, if the device driver is targeted to operate as loadable and removeable kernel module at run time [i.e. using insmod or rmmod command]



回答6:

IN short and crisp way : It starts from .probe and go all the way to init as soon you do insmod .This also registers the driver with the driver subsystem and also initiates the init. Everytime the driver functionalities are called from the user application , functions are invoked using the call back.