Книга: Embedded Linux Primer: A Practical, Real-World Approach
8.3.1. Driver File System Operations
8.3.1. Driver File System Operations
After the device driver is loaded into a live kernel, the first action we must take is to prepare the driver for subsequent operations. The open() method is used for this purpose. After the driver has been opened, we need routines for reading and writing to the driver. A release() routine is provided to clean up after operations when complete (basically, a close call). Finally, a special system call is provided for nonstandard communication to the driver. This is called ioctl(). Listing 8-10 adds this infrastructure to our example device driver.
Listing 8-10. Adding File System Ops to Hello.c
#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) {
printk("hello_open: successfuln");
return 0;
}
static int hello_release(struct inode *inode, struct file *file) {
printk("hello_release: successfuln");
return 0;
}
static ssize_t hello_read(struct file *file, char *buf, size_t count, loff_t *ptr) {
printk("hello_read: returning zero bytesn");
return 0;
}
static ssize_t hello_write(struct file *file, const char *buf, size_t count, loff_t * ppos) {
printk("hello_read: accepting zero bytesn");
return 0;
}
static int hello_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {
printk("hello_ioctl: cmd=%ld, arg=%ldn", cmd, arg);
return 0;
}
static int __init hello_init(void) {
int ret;
printk("Hello Example Init - debug mode is %sn", debug_enable ? "enabled" : "disabled");
ret = register_chrdev(HELLO_MAJOR, "hello1", &hello_fops);
if (ret < 0) {
printk("Error registering hello devicen");
goto hello_fail1;
}
printk("Hello: registered module successfully!n");
/* Init processing here... */
return 0;
hello_fail1:
return ret;
}
static void __exit hello_exit(void) {
printk("Hello Example Exitn");
}
struct file_operations hello_fops = {
owner: THIS_MODULE,
read: hello_read,
write: hello_write,
ioctl: hello_ioctl,
open: hello_open,
release: hello_release,
};
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("Chris Hallinan");
MODULE_DESCRIPTION("Hello World Example");
MODULE_LICENSE("GPL");
This expanded device driver example includes many new lines. From the top, we've had to add a new kernel header file to get the definitions for the file system operations. We've also defined a major number for our device driver. (Note to device driver authors: This is not the proper way to allocate a device driver major number. Refer to the Linux kernel documentation (.../Documentation/devices.txt) or one of the excellent texts on device drivers for guidance on the allocation of major device numbers. For this simple example, we simply choose one that we know isn't in use on our system.)
Next we see definitions for four new functions, our open, close, read, and write methods. In keeping with good coding practices, we've adopted a consistent naming scheme that will not collide with any other subsystems in the kernel. Our new methods are called hello_open(), hello_release(), hello_read(), and hello_write(), respectively. For purposes of this simple exercise, they are do-nothing functions that simply print a message to the kernel log subsystem.
Notice that we've also added a new function call to our hello_init() routine. This line registers our device driver with the kernel. With that registration call, we pass a structure containing pointers to the required methods. The kernel uses this structure, of type struct file_operations, to bind our specific device functions with the appropriate requests from the file system. When an application opens a device represented by our device driver and requests a read() operation, the file system associates that generic read() request with our module's hello_read() function. The following sections examine this process in detail.
- 8.3. Driver Methods
- Generalized identity operations
- Heap operations
- Arithmetic operations
- Logical operations
- Shared Cache file
- 8.5.2 Typical Condition Variable Operations
- JDBC Туре 4 DRIVER
- Безопасность внешних таблиц. Параметр EXTERNAL FILE DIRECTORY
- Chapter 13. rc.firewall file
- System tools used for debugging
- Integrated Secure Communications System