Write a Linux Driver (write a virtual character device)

Source: Internet
Author: User
Tags dmesg


[Disclaimer: All Rights Reserved. You are welcome to reprint it. Do not use it for commercial purposes. Contact Email: feixiaoxing @ 163.com]


Yesterday we talked about some simple module compiling methods, but it did not involve the compilation of devices. Today we can learn about the relevant content, an instance is used to describe how devices are written on Linux. Although I am not dedicated to Linux drivers, I often receive emails from friends. In the letter, many drivers are not very satisfied with their work. They think that their job is to copy and modify the code, no technical skills. There are not a few friends who have such ideas. I think this is mainly because they lack understanding of their work. If possible, we can ask ourselves the following questions:


(1) Do I really understand the device development driver process? Can I write an independent driver code from 0?

(2) Do I know the device initialization, shutdown, and running processes?

(3) is the current device driver process reasonable and can be improved?

(4) Do I really understand and understand the differences between the API calls involved in kernel development?

(5) If the device I want to drive only runs in a front-end and back-end system, will I be confident to start and run it without the help of the framework?


Of course, the above content is only my personal thoughts and is not always correct. However, if you are familiar with the advantages and disadvantages of the current development process, you can truly grasp and understand the nature of driver development. It sounds a bit mysterious. In fact, it is also very simple. It is necessary to have a spirit of root question and continuous improvement so that we can do our jobs well. Because we are learning the driver on PC Linux, there is no real external device available for the moment, but this does not affect our enthusiasm for learning. Through the timer and process, we can simulate various requirements of real devices, so for the system, it does not matter whether real devices or false devices, the basic processing process is the same for it. As long as you do this step by step, you will be able to understand the development project of the Linux driver.


Below, to illustrate the problem, we can write a simple char device driver code named Char. C,

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/cdev.h>static struct cdev chr_dev;static dev_t ndev;static int chr_open(struct inode* nd, struct file* filp){int major ;int minor;major = MAJOR(nd->i_rdev);minor = MINOR(nd->i_rdev);printk("chr_open, major = %d, minor = %d\n", major, minor);return 0;}static ssize_t chr_read(struct file* filp, char __user* u, size_t sz, loff_t* off){printk("chr_read process!\n");return 0;}struct file_operations chr_ops = {.owner = THIS_MODULE,.open = chr_open,.read = chr_read};static int demo_init(void){int ret;cdev_init(&chr_dev, &chr_ops);ret = alloc_chrdev_region(&ndev, 0, 1, "chr_dev");if(ret < 0 ){return ret;}printk("demo_init(): major = %d, minor = %d\n", MAJOR(ndev), MINOR(ndev));ret = cdev_add(&chr_dev, ndev, 1);if(ret < 0){return ret;}return 0;}static void demo_exit(void){printk("demo_exit process!\n");cdev_del(&chr_dev);unregister_chrdev_region(ndev, 1);}module_init(demo_init);module_exit(demo_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("feixiaoxing@163.com");MODULE_DESCRIPTION("A simple device example!");

The functions in module_init are the functions processed during module loading, while the functions uninstalled by the module are in module_exit. Each device must correspond to a basic device data. Of course, in order for the device to be registered in the entire system, we also need to allocate a device node, and alloc_chrdev_region will complete this function. When cdev_add is complete, the entire device registration process is complete. Of course, to write this file, we also need to write a MAKEFILE file,

ifneq ($(KERNELRELEASE),)obj-m := char.oelsePWD  := $(shell pwd)KVER := $(shell uname -r)KDIR := /lib/modules/$(KVER)/buildall:$(MAKE) -C $(KDIR) M=$(PWD) modulesclean:rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.*  Module.*endif

This MAKEFILE file is basically the same as the makefile we wrote earlier. The only difference is that the file name is changed to Char. O, that's all. To compile the module, enter make directly. In this case, the char. Ko file can be generated. Then, the module needs to be registered in the system, and insmod Char. Ko is indispensable. If you are not sure whether the module has been added to the system, you can enter lsmod | grep char for search and verification. To create a device node, we need to know the major and minor values created by the device for us. So dmesg | tail looks for the values. On my HP machine, these two values are 249 and 0 respectively, so you can use them to directly create a device node. Enter mknod/dev/chr_dev C 249 0, enter ls/dev/chr_dev for verification. So, in this way, can I access this virtual device? We can write a simple code to verify it,

#include <stdio.h>#include <fcntl.h>#include <unistd.h>#define CHAR_DEV_NAME "/dev/chr_dev"int main(){int ret;int fd;char buf[32];fd = open(CHAR_DEV_NAME, O_RDONLY | O_NDELAY);if(fd < 0){printf("open failed!\n");return -1;}read(fd, buf, 32);close(fd);return 0;}

The code is very simple, that is, the char_dev_name is used to directly open the device, read and write the device. Of course. First, you need to compile the file named test. C, input GCC test. C-O test, and then run the file and enter./test. If there is no problem, our code is OK, but we still haven't seen anything. It doesn't matter. We can still use the dmesg command to check whether there is related print content in the kernel, and directly enter dmesg | tail. In this case, we can see the printk printing left in chr_open and chr_read. This shows that our code is completely OK.


The above code is just a small example. The actual content is more complicated than this. However, since we are all getting started, there is nothing to worry about later content. There are two things to add: (1) If you want to delete a device node after creating a node, you can directly Rm-RF/dev/chr_dev; (2) the prototype of the above Code is from the book deep into the Linux Device Driver kernel mechanism, which is slightly modified. If you are interested in the content of the kernel mechanism, you can refer to the content of this book.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.