1. 程式人生 > >linux驅動開發(三) 字符設備驅動框架(自動創建設備節點)

linux驅動開發(三) 字符設備驅動框架(自動創建設備節點)

The module __line__ mage fail goto div on() sys

代碼如下

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>  


int demo_major = 250;
int demo_minor = 0;
int demo_count = 1;

struct cdev cdev;

static struct class *demo_class;
static struct device *demo_device; int demo_open(struct inode *inodep, struct file * filep) // 打開設備 { printk("%s,%d\n", __func__, __LINE__); return 0; } int demo_release(struct inode * inodep, struct file * filep) // 關閉設備 { printk("%s,%d\n", __func__, __LINE__); return 0; } struct file_operations fops = { .owner
= THIS_MODULE, .open = demo_open, .release = demo_release, }; static int __init demo_init(void) { int ret = 0; dev_t devno; printk("%s,%d\n", __func__, __LINE__); //使用下列宏則可以通過主設備號和次設備號生成 dev_t devno = MKDEV(demo_major, demo_minor); printk("devno:%d\n", devno); printk(
"demo_major:%d\n", demo_major); /**在調用 cdev_add()函數向系統註冊字符設備之前, *應首先調用 register_chrdev_region()或alloc_chrdev_region()函數向系統申請設備號 **/ if (demo_major) {
     //使用cat /proc/devices | grep demo 來查詢 ret
= register_chrdev_region(devno, 1, "demo"); } else { ret = alloc_chrdev_region(&devno, demo_minor, 1, "demo"); } if(ret) { printk("Failed to register_chrdev_region.\n"); return ret; } //cdev_init()函數用於初始化 cdev 的成員,並建立 cdev 和 file_operations 之間的連接 cdev_init(&cdev, &fops); cdev.owner = THIS_MODULE; //系統添加一個 cdev,完成字符設備的註冊。 ret = cdev_add(&cdev, devno, demo_count); if(ret) { printk(KERN_NOTICE " Failed to cdev_add [Error] %d adding demo%d", ret, demo_minor); goto failure_cdev_add; } /*自動創建設備節點文件*/ //1.註冊設備類 /sys/class/demo的文件夾
  //使用 ls /sys/class/demo
demo_class = class_create(THIS_MODULE, "demo"); if( IS_ERR(demo_class)) { printk("class_create failed!\n"); ret = PTR_ERR("demo_class"); goto failure_class_create; } //2.註冊設備 /sys/class/demo/demo0 /dev/demo0 demo_device = device_create(demo_class, NULL, MKDEV(demo_major, demo_minor), NULL, "demo%d", demo_minor); if(IS_ERR(demo_device)){ printk("device_create failed!\n"); ret = PTR_ERR("demo_device"); goto failure_device_create; } return 0; failure_device_create: class_destroy(demo_class); failure_class_create: cdev_del(&cdev); failure_cdev_add: unregister_chrdev_region(devno, demo_count); failure_register_chrdev: return ret; } static void __exit demo_exit(void) { printk("%s,%d\n", __func__, __LINE__); /*逆序消除*/ //從內核中刪除設備 device_destroy(demo_class,MKDEV(demo_major, demo_minor)); //從內核中刪除設備類 class_destroy(demo_class); //刪除一個 cdev,完成字符設備的註銷。 cdev_del(&cdev); //在調用cdev_del()函數從系統註銷字符設備之後,unregister_chrdev_region()應該被調用以釋放原先申請的設備號 unregister_chrdev_region( MKDEV(demo_major, demo_minor), demo_count ); } module_init(demo_init); module_exit(demo_exit); MODULE_AUTHOR(" libra13179 "); MODULE_LICENSE("GPL v2");

技術分享圖片
KVERS = $(shell uname -r)

# Kernel modules
obj-m += demo.o

# Specify flags for the module compilation.
#EXTRA_CFLAGS=-g -O0

build: kernel_modules

kernel_modules:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
#    @echo $(KVERS)

clean:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
View Code

技術分享圖片
#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>





int main(int argc, const char *argv[])

{

    int fd;

    int val = 1;

    fd = open("/dev/demo0", O_RDWR);

    if (fd < 0)

    {

        printf("can‘t open!\n");

        return -1;

    }

    else

    {

        printf("open success.\n");

    }

 

 

    getchar();

 

 

    close(fd);



    return 0;

}
View Code

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

linux驅動開發(三) 字符設備驅動框架(自動創建設備節點)