Presentation is loading. Please wait.

Presentation is loading. Please wait.

Interfacing Device Drivers with the Kernel

Similar presentations


Presentation on theme: "Interfacing Device Drivers with the Kernel"— Presentation transcript:

1 Interfacing Device Drivers with the Kernel
Each class of device driver, character, block and network, provides common interfaces that the kernel uses when requesting services from them. These common interfaces mean that the kernel can treat often very different devices and their device drivers absolutely the same. For example, SCSI and IDE disks behave very differently but the Linux kernel uses the same interface to both of them.

2 Linux allows you to include device drivers at kernel build time via its configuration scripts. When these drivers are initialized at boot time they may not discover any hardware to control. Other drivers can be loaded as kernel modules when they are needed. To cope with this dynamic nature of device drivers, device drivers register themselves with the kernel as they are initialized. Linux maintains tables of registered device drivers as part of its interfaces with them. These tables include pointers to routines and information that support the interface with that class of devices.

3

4

5 #include <linux/module.h>
#include <linux/fs.h> #define HELLO_MAJOR 234 static int debug_enable = 0; module_param(debug_enable, int, 0); MODULE_PARM_DESC(debug_enable, “Enable module debug mode.”); struct file_operations hello_fops; static int hello_open(struct inode *inode, struct file *file)

6 static int hello_open(struct inode. inode, struct file
static int hello_open(struct inode *inode, struct file *file) { printk(“hello_open: successful\n”); return 0; } static int hello_release(struct inode *inode, struct file *file) printk(“hello_release: successful\n”); static ssize_t hello_read(struct file *file, char *buf, size_t count, loff_t *ptr) printk(“hello_read: returning zero bytes\n”); static ssize_t hello

7 Some Important Data Structures
Connecting of driver’s operations to numbers is been done with file_operations structure defined in <linux/fs.h> Each open file (represented internally by a file structure, is associated with its own set of functions (by including a field called f_op that points to a file_operations structure). struct file , defined in <linux/fs.h> is the second most important data structure used in device drivers Inode structure : The inode structure is used by the kernel internally to represent files. dev_t i_rdev; For inodes that represent device files, this field contains the actual device number. struct cdev *i_cdev; struct cdev is the kernel’s internal structure that represents char devices; this field contains a pointer to that structure when the inode refers to a char device file. .

8 static int hello_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) { printk(“hello_ioctl: cmd=%ld, arg=%ld\n”, cmd, arg); return 0; } static int __init hello_init(void) int ret; printk(“Hello Example Init - debug mode is %s\n”, debug_enable ? “enabled” : “disabled”); ret = register_chrdev(HELLO_MAJOR, “hello1”, &hello_fops); if (ret < 0) { printk(“Error registering hello device\n”); goto hello_fail1; printk(“Hello: registered module successfully!\n”);

9 static int __init hello_init(void) { int ret; printk(“Hello Example Init - debug mode is %s\n”, debug_enable ? “enabled” : “disabled”); ret = register_chrdev(HELLO_MAJOR, “hello1”, &hello_fops); if (ret < 0) { printk(“Error registering hello device\n”); goto hello_fail1; } printk(“Hello: registered module successfully!\n”);

10 struct file_operations hello_fops = {
owner: THIS_MODULE, read: hello_read, write: hello_write, ioctl: hello_ioctl, open: hello_open, release: hello_release, };

11 Device Nodes and mknod $ mknod /dev/hello1 c 234 0 ls -l /dev/hello1 crw-r--r-- 1 root root 234, 0 Jul /dev/hello1

12 Character devices, the simplest of Linux's devices, are accessed as files, applications use standard system calls to open them, read from them, write to them and close them exactly as if the device were a file. This is true even if the device is a modem being used by the PPP daemon to connect a Linux system onto a network. As a character device is initialized its device driver registers itself with the Linux kernel by adding an entry into the chrdevs vector of device_struct data structures. The device's major device identifier (for example 4 for the tty device) is used as an index into this vector. The major device identifier for a device is fixed.

13 Each entry in the chrdevs vector, a device_struct data structure contains two elements;
a pointer to the name of the registered device driver and a pointer to a block of file operations. This block of file operations is itself the addresses of routines within the device character device driver each of which handles specific file operations such as open, read, write and close. The contents of /proc/devices for character devices is taken from the chrdevs vector. When a character special file representing a character device (for example /dev/cua0) is opened the kernel must set things up so that the correct character device driver's file operation routines will be called. Just like an ordinairy file or directory, each device special file is represented by a VFS inode . The VFS inode for a character special file, indeed for all device special files, contains both the major and minor identifiers for the device. This VFS inode was created by the underlying filesystem, for example EXT2, from information in the real filesystem when the device special file's name was looked up.

14 Each VFS inode has associated with it a set of file operations and these are different depending on the filesystem object that the inode represents. Whenever a VFS inode representing a character special file is created, its file operations are set to the default character device operations . This has only one file operation, the open file operation. When the character special file is opened by an application the generic open file operation uses the device's major identifier as an index into the chrdevs vector to retrieve the file operations block for this particular device. It also sets up the file data structure describing this character special file, making its file operations pointer point to those of the device driver. Thereafter all of the applications file operations will be mapped to calls to the character devices set of file operations.

15 Each device and its device file has associated with it, a unique Major number and a Minor number. No two devices have the same major number.  When a device file is opened, Linux examines its major number and forwards the call to the driver registered for that device.  Subsequent calls for read/write/close too are processed by the same driver. As far as kernel is concerned, only major number is important. Minor number is used to identify the specific device instance if the driver controls more than one device of a type. A Linux driver is a Linux module which can be loaded and linked to the kernel at runtime. The driver operates in kernel space and becomes part of the kernel once loaded, the kernel being monolithic. It can then access the symbols exported by the kernel. When the device driver module is loaded, the driver first registers itself as a driver for a particular device specifying a particular Major number.

16 It uses the call register_chrdev function for registration
It uses the call register_chrdev function for registration. The call takes the Major number, Minor number, device name and an address of a structure of the type file_operations(discussed later) as argument. In our example, we will be using a major number of 89 . The choice of major number is arbitrary but it has to be unique on the system. The syntax of register_chrdev is int register_chrdev(unsigned int major,const char *name,struct file_operations *fops)

17 the make command required to build your module
(typed in the directory containing the module source and makefile) would be: make -C ~/kernel-2.6 M=`pwd` modules This command starts by changing its directory to the one provided with the -C option (that is, your kernel source directory). There it finds the kernel’s top-level makefile. The M= option causes that makefile to move back into your module source directory before trying to build the modules target. This target, in turn, refers to the list of modules found in the obj-m variable, which we’ve set to module.o in our examples.


Download ppt "Interfacing Device Drivers with the Kernel"

Similar presentations


Ads by Google