Contents
- Blog description
- Development environment
- 1. Linux character device driver composition
- 1.1 Character device driver module loading and unloading functions
- 1.2 Character device driver in the file_operations structure Member function
- 2. Character device driver-device number registration and uninstallation
- 2.1 Device number registration
- 2.2 Device number cancellation< /li>
- 3. Character device driver-file operation
- Reference material
- Sample code
< /div>
@(Understand the development process of character device driver from the Linux kernel LED driver)
blog description
Date of writing | 2018.12.08 |
---|---|
Date of completion | 2019.10.06 |
Recently maintained | none |
author of this article | multimicro |
Contact information | [email protected] |
GitHub | https://github.com/wifialan |
The address of this article | https://blog.csdn.net/multimicro/article/details/84898135 |
Development environment
Environment description | Detailed information | Remarks |
---|---|---|
Operating system | Ubunut 18.04.3 LTS | |
Development board | S3C2440(JZ2440-V3) | |
linux-3.4.2 | Official website address | |
busybox version | busybox-1.22.1 | Official website address |
Compiler | arm-li nux-gcc-4.4.3 | Download URL |
Compiler path | /opt/FriendlyARM/toolschain/4.4.3/bin | absolute path |
1. Linux character device driver composition
Quoted from Song Baohua “Linux Device Driver Development Detailed Explanation–Based on the Latest Linux 4.0 Kernel” P138 content:
In Linux, the character device driver is composed of the following parts.
1. Character device driver module loading and unloading functions
2. Member functions in the file_operations structure of the character device driver
Let’s first introduce the development process of the character device: the character device driver is connected to the host computer program through the device number. The upper computer program controls the driver through file operations, that is, read, write, ioctl
and so on.
- ps. (For Linux systems, everything is a file. After the driver is loaded successfully, the driver node number information will be added in
/proc/devices
) li>
So a character device driver should contain 1. Device number registration, uninstallation
and 2. File operation
two functions, registered device The number is used to provide an interface, and the file operation is used to operate the drive.
The structure of the character device driver is shown in the figure below:
void cdev_init(struct cdev *cdev, const struct file_operations *fops){ memset(cdev, 0, sizeof *cdev); INIT_LIST_HEAD(&cdev->list); kobject_init(&cdev- >kobj, &ktype_cdev_default); cdev->ops = fops;}
It can be seen that the last statement cdev->ops = fops;
completes the < code>file_operations binding
Let’s get a perceptual understanding of the registration and uninstallation function prototypes of the device number, and the file operation function prototypes from the perspective of the programming language.
1.1 Character device driver module loading and unloading functions
//Loading function static int __init xxx_init(void){ ... ...}//Unloading function static int __exit xxx_exit(void){ ... ...}
1.2 member functions in the file_operations structure of the character device driver
static const struct file_operations xxx_fileops = {.owner = THIS_MODULE, .write = xxx_write, .read = xxx_read , .open = xxx_open, .unlocked_ioctl = xxx_ioctl, ... ...};static int xxx_open( struct inode *inodes, struct file *filp ){ ... ...}static long xxx_ioctl( struct file *file, unsigned int cmd, unsigned long arg ){ ... ...}static ssize_t xxx_write( struct file *filp, const char __user *buffer, size_t size, loff_t *f_pos ){ ... ...}static ssize_t xxx_read( struct file *filp, const char __user *buffer, size_t size, loff_t *f_pos ){ ... ...}
2. Character device driver— —Device number registration and uninstallation
Take the character device driver source code I wrote as an example, the path is linux-3.4.2\drivers\char\s3c2440_leds.c
, the article is attached There is a complete code
The registration of the device number is completed by static int __init s3c2440_leds_init(void)
The uninstallation of the device number is completed by static int __init s3c2440_leds_exit(void)
First analyze the registration of the device number, and then analyze the uninstallation
2.1 Device number registration
The device number is divided into a major device number and a minor device number. If the major device number is defined in the source code (the minor device number is generally 0), then the registration of the device number can be completed directly, and the process is
After successful registration, you can access cat /proc/devicesCommand to view the device number
2.2 Device number cancellation
Compared with device number registration, the cancellation process is very simple:
3. Character device driver-file operation
When the host computer program After the corresponding driver is opened (on the link) by calling the open
function, the open
function will return a == file descriptor == temporarily recorded as fd code>, and then
read, write, ioctl
and other operations of the driver can be completed by using fd
. Simple character device drivers mostly use the ioctl
function to control the driver, and this ioctl
function itself is not difficult, its implementation is:
static long s3c2440_leds_ioctl( struct file *file, unsigned int cmd, unsigned long arg )
The first parameter in the function
: indicates the file descriptor to be operated on
The second parameter: indicates the command word passed
The third parameter: indicates the variable word passed
The meaning of the second parameter and the third parameter has no hard and fast rules, and the passed parameters comply with the corresponding The keyword can limit the type.
The example reference is given below
static long s3c2440_leds_ioctl( struct file *file, unsigned int cmd, unsigned long arg ){ printk(DRV_NAME "\tRecv cmd: %u\n", cmd); printk(DRV_NAME "\tRecv arg: %lu\n", arg); //IO operations function. if(arg> 4) {return -EINVAL ;} switch (cmd) {case IOCTL_LED_ON: //#define IOCTL_LED_ON 1 s3c2410_gpio_setpin(S3C2410_GPF(arg+3), 0);//Set pin printk("Open LED %lu ",arg); return 0; case IOCTL_LED_OFF: //#define IOCTL_LED_OFF 0 s3c2410_gpio_setpin(S3C2410_GPF(arg+3), 1); printk("Close LED %lu ",arg); return 0; default : return -EINVAL; }}
Reference Materials
1. Song Baohua "Linux Device Driver Development Detailed Explanation-Based on the Latest Linux 4.0 Kernel"< /strong> Chapter 6 Character Device Driver
Sample Code
/* * Driver for S3C2440 base board. * * Copyright (C ) 2019 Alan NWPU <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * MULTIBEANS, NP U Youyi West Ave, Beilin District, Xi'an, China. */#include/* Every Linux kernel module must include this head */#include /* Every Linux kernel module must include this head */#include /* printk() */#include /* struct fops */#include /* error codes */#include /* cdev_alloc() */#include /* request_mem_region() */#include #include #include #include #include #include #include # include #include #include #include #include #include #include #define DRV_NAME "s3c2440_leds"#define DRV_AUTHOR "Alan Tian <[email protected]>"#define DRV_DESC "S3C2440 LED Pin Driver"#define S3C2440_LED_SIZE 0x1000#define S3C2440_LED_MAJOR 230#define S3C2440_LED_MI NOR 0 static int major = S3C2440_LED_MAJOR; static int minor = S3C2440_LED_MINOR; /* The second parameter when the application executes ioctl(fd, cmd, arg)*/#define IOCTL_LED_ON 0#define IOCTL_LED_OFF 1static int s_opendes s3c2440, struct struct file *filp );static long s3c2440_leds_ioctl( struct file *file, unsigned int cmd, unsigned long arg );static ssize_t s3c2440_leds_write( struct file *filp, const char __user *buffer, size_t size, loff_t static_t *3creadsize_t *3creadsize_t ); (struct file *filp, const char __user *buffer, size_t size, loff_t *f_pos );struct s3c2440_leds_dev_t{ struct cdev cdev; unsigned char mem[S3C2440_LED_SIZE];} *s3c2440_LED_SIZE];) *s3c2440_LED_SIZE];) *s3c2440_LED_SIZE = {.owner = THIS_MODULE, .write = s3c2440_leds_write, .read = s3c2440_leds_read, .open = s3c2440_leds_open, .unlocked_ioctl = s3c2440_leds_ioctl,};static int s3c2 440_leds_open( struct inode *inodes, struct file *filp ){ //int ret; filp->private_data = s3c2440_leds_dev; printk(DRV_NAME"\tS3C2440 open function...\n"); return 0;}static long s3c2440_leds_ioctl( struct file *file, unsigned int cmd, unsigned long arg ){ printk(DRV_NAME "\tRecv cmd: %u\n", cmd); printk(DRV_NAME "\tRecv arg: %lu\n", arg); //IO operations function. if(arg> 4) {return -EINVAL;} switch (cmd) {case IOCTL_LED_ON: s3c2410_gpio_setpin(S3C2410_GPF(arg+3), 0);//Set pin printk("Open LED %lu ",arg) ; return 0; case IOCTL_LED_OFF: s3c2410_gpio_setpin(S3C2410_GPF(arg+3), 1); printk("Close LED %lu ",arg); return 0; default: return -EINVAL; })static ssize_t s3c2440_leds_write( struct file *filp , const char __user *buffer, size_t size, loff_t *f_pos ){ unsigned long p = *f_pos; unsigned int count = size; int ret = 0; struct s3c2440_leds_dev_t *dev = filp->private_data; if(p >= S3C2440_LED_SIZE) return 0; if(count> S3C2440_LED_SIZE-p) count = S3C2440_LED_SIZE-p; memset(dev->mem), 0, S3ZE2440_LED if(copy_from_user(dev->mem + p, buffer, count)) {ret = -EFAULT;} else {*f_pos += count; ret = count; printk(KERN_INFO "writter %u bytes(s) from %lu\ n", count, p);} return ret; }static ssize_t s3c2440_leds_read( struct file *filp, const char __user *buffer, size_t size, loff_t *f_pos ){ unsigned long p = *f_pos; unsigned int count = size; int ret = 0; struct s3c2440_leds_dev_t *dev = filp->private_data; if(p >= S3C2440_LED_SIZE) return 0; if(count> S3C2440_LED_SIZE-p) count = S3C2440_LED_SIZE-p; if(copy_to_user(mem +, p dev-> , count)) {ret = -EFAULT;} else {*f_pos += count; ret = count; printk(KERN_ INFO "read %u bytes(s) from %lu\n", count, p);} return ret;}static int __init s3c2440_leds_init(void){ int ret,err; dev_t devid; if(major) {devid = MKDEV (major, 0); ret = register_chrdev_region(devid, 1, DRV_NAME); printk("Origin Creat node %d\n",major);} else {ret = alloc_chrdev_region(&devid, 0, 1, DRV_NAME); major = MAJOR(devid); printk("Arrage1 Creat node %d\n",major);} if(ret <0) {printk(DRV_NAME "\ts3c2440 new device failed\n"); //goto fail_malloc; return ret; } s3c2440_leds_dev = kzalloc(sizeof(struct s3c2440_leds_dev_t), GFP_KERNEL); if(!s3c2440_leds_dev) {ret = -ENOMEM; goto fail_malloc;} printk("success init leds\nc_40";s_dev24leds-dev_sop_dev); err = cdev_add(&s3c2440_leds_dev->cdev, devid, 1); if(err) printk(KERN_NOTICE "Error %d adding s2c2440_leds %d",err, 1); return 0; fail_malloc: unr egister_chrdev_region(devid, 1); return ret;}static void __exit s3c2440_leds_exit(void){ printk("Starting delet node %d\n",major); cdev_del(&s3c2440_leds_dev->cdev); kfree(s3c2440_leds_dev); unregister (major, minor), 1); printk("Delete node %d\n",major);}module_init(s3c2440_leds_init);module_exit(s3c2440_leds_exit);MODULE_AUTHOR(DRV_AUTHOR);MODULE_DESCRIPLICTION(DRV_DES_C");MODULE_DESCRIPLICTION(DRV_DES_C"); ;
Contents
- Blog description
- 1. Composition of Linux character device driver
- 1.1 Load and unload functions of character device driver module
- 1.2 In the file_operations structure of character device driver Member functions of
- 2. Character device driver-device number registration and uninstallation
- 2.1 Device number registration
- 2.2 Device number cancellation
- 3. Character device driver-file operation
- Reference material
- Sample code
< li>Development environment
- Blog description
- Development environment
- 1. Linux character device driver composition
- 1.1 Character device driver module loading and unloading functions
- 1.2 Member functions in the file_operations structure of the character device driver
- 2 . Character device driver-device number registration and uninstallation
- 2.1 Device number registration
- 2.2 Device number cancellation
- 3. Character device Drive-file operation
- Reference material
- Sample code
WordPress database error: [Table 'yf99682.wp_s6mz6tyggq_comments' doesn't exist]SELECT SQL_CALC_FOUND_ROWS wp_s6mz6tyggq_comments.comment_ID FROM wp_s6mz6tyggq_comments WHERE ( comment_approved = '1' ) AND comment_post_ID = 5141 ORDER BY wp_s6mz6tyggq_comments.comment_date_gmt ASC, wp_s6mz6tyggq_comments.comment_ID ASC