In the previous article, we introduced how to compile a module in Linux and load it to the kernel space. Through the experiment, we learned about the general process and the working principle of the module. This article describes how to write a virtual character device driver.
The main reason is that the driver does not really operate on external devices. It is just a character device driver framework, this laid the foundation for the development of the device drivers (LED, buzzer, etc.
Author: canghai hunter Source: http://blog.csdn.net/embedded_hunter reproduced please indicate the source of embedded technology exchange QQ group: 179012822
I. experiment environment
Development machine environment
Operating System: Ubuntu 9.10
Cross-compiling environment: Arm-Linux-GCC 4.2.2, installation location/usr/local/ARM/4.3.2/
6410 board kernel source code path:/work/linux-2.6.36.2-v1.05/
Target Board Environment: OK6410-A linux2.6.36
Ii. Experiment Principles
In Linux, we often hear "Everything is a file ". The operation on the device is converted to the operation on the file. In this case, operations on files in the user space include open, read, write, and close. So how does one respond to file operation requests sent by users in the driver?
Through this experiment, I will first understand the general process, and then I will gradually introduce the specific details to you.
Iii. Experiment steps
1. Write the driver
Driver_char.c
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <asm/uaccess.h> /* copy_to_user,copy_from_user */#define MY_MAJOR 240int my_open (struct inode *inode,struct file *filp){printk("#########open######\n");return 0;}ssize_t my_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos){printk("#########read######\n");return count;}ssize_t my_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos){printk("#########write######\n");return count;}int my_release (struct inode *inode, struct file *filp){printk("#########release######\n");return 0;}struct file_operations my_fops ={.owner = THIS_MODULE,.open = my_open,.read = my_read,.write = my_write,.release = my_release,};int __init my_init (void){int rc;printk ("Test char dev\n");rc = register_chrdev(MY_MAJOR,"my",&my_fops);if (rc <0){printk ("register %s char dev error\n","my");return -1;}printk ("ok!\n");return 0;}void __exit my_exit (void){unregister_chrdev(MY_MAJOR,"my");printk ("module exit\n");}MODULE_LICENSE("GPL");module_init(my_init);module_exit(my_exit);
Makefile
obj-m := driver_char.oKDIR :=/work/linux-2.6.36.2-v1.05/all:make -C $(KDIR) M=$(shell pwd) modulesinstall:cp driver_char.ko /tftpboot/clean:make -C $(KDIR) M=$(shell pwd) clean
2. Compile the test program
Test. c
#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int main (void){int fd;char buf[10]={0,1};char buf2[10];fd = open("/dev/my_char",O_RDWR);if (fd < 0){printf ("Open /dev/my_char");return -1;}write(fd,buf,2);read(fd,buf2,2);close (fd);return 0;}
3. Compile the driver and test program
Compile the driver
# Make
Place the driver in the TFTP working directory/tftpboot
# Make install
Compile the test program
# Arm-Linux-GCC test. C-o Test
Put the test program to the TFTP working directory/tftpboot
# Cp test/tftpboot
4. Download the program to the Development Board
Modify the IP address of the Development Board in the same CIDR block as the host. Make sure that the TFTP service of the PC is enabled.
Download the program to the Development Board
Smdk6410 # TFTP-L/lib/modules/2.6.36.2/driver_char.ko-r driver_char.ko-G 192.168.1.111192.168.1.111 is the Server IP Address
Smdk6410 # TFTP-l test-r test-G 192.168.1.111
5. Test
Load the driver # insmod/lib/modules/2.6.36.2/driver_char.ko
Create the device file # mknod/dev/my_char C 240 0
Test./test
[Root @ forlinx6410] #./test
######## Open ######
######### Write ######
######### Read ######
######### Release ######
Uninstall the driver # rmmod driver_char
From the above results, we can see that when you call the corresponding file operation function, the corresponding function in the driver will also be called.
You can modify the corresponding program to test other cases.
Author: canghai hunter Source: http://blog.csdn.net/embedded_hunter reproduced please indicate the source of embedded technology exchange QQ group: 179012822
Note: This driver uses the most basic kernel functions. The operation method may be different from other drivers you have seen, especially the functions for registering character devices. It doesn't matter. We will introduce other related functions step by step.