| Loadable Kernel Module - LKM exists from the kernel Linux 1.3 (1995).
- A kernel module is a piece of code which can be loaded and unloaded into the kernel on demand. They help in the extending the functionality of kernel without need to rebuild and reboot the kernel every time we want new functionality.One type of moduel is device driver, which allows the kernel to access the hardware resource. - Each device is identified by kernel as two numbers (major number and minor number ) major number tells which device driver is used to access the hardware.And minor number is used by driver to distinguish between various hardware it controls. Suppose i have 3 different floppy devices conected to a pc, then all floppy devices will be accessed with the help of a floppy driver ( has major no) and each device will have a unique minor number differentiating the devices. - When a device file is accessed, kernel uses the major number of the file to determine which driver should be used to handle the access.The driver will then use the minor numbers to distinguish the different piece of hardware. - mknod command is used to create a new device file under /dev directory. mknod /dev/myown c 255 0 (ex). - Application performs a single task from beginning to end. But a module registers itself inorder to perform a future rquests and its main is terminated immediately. - init_module is the entry point for a module whnen its loaded and cleanup_module gets invoked just before the module is unloaded from kernel. - An application can call function it doesnot define through linking with other libraries.But module is linked only to functions exported by kernel.So No libraries that it can link to. - Modules stacking. - the printk messages ex. printk("<1> Hello world"); or printk(KERN_ALERT "Hello world\n"); In an xterm these messages will not be displayed in TTY, rather it is logged into a system log files /var/log/messages - Usage count - The system keeps a usage count for every module in order to determine whether the module can be safely removed.System needs this information because the module cannot be unloaded if it is busy.Modern kernel keep track of this count automatically for you. There are some times, when we need to adjust the usage manually. The macros used for this purposes are MOD_INC_USE_COUNT - Increments the count for the current module. MOD_DEC_USE_COUNT - Decrements the count. MOD_IN_USE - Evaluates to true if the count is not zero. These macros are define in <linux/module.h> (/usr/include/linux/module.h) - We shld call MOD_INC_USE_COUNT before doing almost everything else in the module.We wont be able to unload a module in case we loose track of usage count.For example if a process gets destroyed because your driver dereferenced a NULL pointer, the driver wont be able to close the device and usage wont reduce to zero. - The current value of the usage count is found in the third field of each entry in /proc/modules. The fields are name of the module, number of bytes of memory it uses, current usage count. - insmod - is just like ld program, which links any unresolved symbols in the module to the symbol table of the running kernel - In modern kernels from 2.3.13, the facility exists for naming the module intialisation and cleanup routines. module_init(my_init) module_exit(my_cleanup) We must include <linux/init.h> to use those macros. insmod inturnally does three steps 1) sys_create_module - allocates kernel memory to hold a module 2) get_kernel_syms - trtunr the symbol table so that kernel references in the module can be resolved. 3) sys_init_module copies the relocated object code to kernel space and calls the modules initialisation function. https://cepserver.tce.edu/pipermail/glugot/2005-May/000186.html - lsmod get the information about the module which are already loaded into the kernel by reading the file /proc/module - register_chrdev() function returns the major no allocated if the caller requests dynamice major number. otherwise returns 0 when successfuly registering a predefined major umber. returns a negative number base on error codes. - unregister_chrdev() function is called when rmmod for a module is invoked.It takes 2 arguments , int- major no being released, char * - name of the associated device name - Kernel compares the passed name in unregister_chrdev() function to the name registered for the major number. So not matches returns ENIVAL. - In the cleanUp_module function - it is necessary to call unregister_chrdev() to unregister the module to release the major number. Failing to do so has unpleasant effects. /proc/devices file will generate a fault when the next time we try to read it, becoz one of the entry (name)string in tat file points to module memory which no longer exists. They system might crash when u do cat /proc/devices itself. - The combined device number (major + minor ) resides in the field i_rdev of the inode structure. Some driver functions receive a pointer to struct inode as a first argument.so inode->i_rdev will reterive the major+minor number. - kdev_t , dev_t hold the device numbers. - A opened device is identified internally by a file structure - 'struct file_operations' . kernel uses this structure to access the drivers functions. Defined in <linux/fs.h> file_operations is a structure cotaining function pointers. Each file is associated with its own set of functions. So whenever a system call on a file is called, kernel will look into tthe structure corresponding to that file and call function pointing to that system call (i.e open,read etc). - The most commonly used file operations are open,read,write,flush,release,ioctl,llseek,mmap,fsync,lock,poll . For portability,tagged initialisation format is used by kernel devlopers when initialising these function pointers.It allows reordering of the structure members during initialisation. ex struct file_operations fops= { open:myown_open, write:myown_write, ioctl:myown_ioctl}; - The owner field(first field) of the struct file_oprations has to be set to the value THIS_MODULE or using the macro from 2.5 kernel SET_MODULE_OWNER.This field is used to prevent the module from being unloaded while its operations are in use. All the times it is initalised to THIS_MODULE - <linux module.h> - structure 'file' represents an open file. Every open file in the system has an associated struct file in kernel space, not known to the user.It is created by kernel on open and is passed to any function that operates on that file,until the last close. After all releases of the file are closed, the kernel releases this data structure. - important fields of struct file are modet_t f_mode, f_pos, f_flags, strcut file_operations *f_op, void *private_data. f_op tells the operations associated with the file. kernel assigns the pointer as a part of implementation of open, and reads it when it needs to dispatch any operations made on that file by a user. The value of filep->f_op is never saved for later reference, means we can change the file operations associated with the file whenever we want. Ex. the code for open associated with majornumber 1 (/dev/null, /dev/zero) substitutes the operations in filep->f_op depending on the minor umber being opened. - Void *private_data is set to NULL before calling the open method for the driver. The driver can use this field to point to allocated data and shld free the memory in the release method before kernel destroys the file structure. It is a useful field to store the state information across the system calls. |