十六、字符驱动及应用
生活随笔
收集整理的這篇文章主要介紹了
十六、字符驱动及应用
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、 驅(qū)動代碼(char_driver.c)
/*包含初始化宏定義的頭文件,代碼中的module_init和module_exit在此文件中*/ #include <linux/init.h> /*包含初始化加載模塊的頭文件,代碼中的MODULE_LICENSE在此頭文件中*/ #include <linux/module.h> /*定義module_param module_param_array的頭文件*/ #include <linux/moduleparam.h> /*定義module_param module_param_array中perm的頭文件*/ #include <linux/stat.h> /*三個(gè)字符設(shè)備函數(shù)*/ #include <linux/fs.h> /*MKDEV轉(zhuǎn)換設(shè)備號數(shù)據(jù)類型的宏定義*/ #include <linux/kdev_t.h> /*定義字符設(shè)備的結(jié)構(gòu)體*/ #include <linux/cdev.h> /*分配內(nèi)存空間函數(shù)頭文件*/ #include <linux/slab.h>/*包含函數(shù)device_create 結(jié)構(gòu)體class等頭文件*/ #include <linux/device.h>#define DEVICE_NAME "chardevnode" #define DEVICE_MINOR_NUM 2 #define DEV_MAJOR 0 #define DEV_MINOR 0 #define REGDEV_SIZE 3000MODULE_LICENSE("Dual BSD/GPL"); /*聲明是開源的,沒有內(nèi)核版本限制*/ MODULE_AUTHOR("iTOPEET_dz"); /*聲明作者*/int numdev_major = DEV_MAJOR; int numdev_minor = DEV_MINOR;/*輸入主設(shè)備號*/ module_param(numdev_major,int,S_IRUSR); /*輸入次設(shè)備號*/ module_param(numdev_minor,int,S_IRUSR);static struct class *myclass;struct reg_dev {char *data;unsigned long size;struct cdev cdev; }; struct reg_dev *my_devices; /*打開操作*/ static int chardevnode_open(struct inode *inode, struct file *file){printk(KERN_EMERG "chardevnode_open is success!\n");return 0; } /*關(guān)閉操作*/ static int chardevnode_release(struct inode *inode, struct file *file){printk(KERN_EMERG "chardevnode_release is success!\n");return 0; } /*IO操作*/ static long chardevnode_ioctl(struct file *file, unsigned int cmd, unsigned long arg){printk(KERN_EMERG "chardevnode_ioctl is success! cmd is %d,arg is %d \n",cmd,arg);return 0; }ssize_t chardevnode_read(struct file *file, char __user *buf, size_t count, loff_t *f_ops){return 0; }ssize_t chardevnode_write(struct file *file, const char __user *buf, size_t count, loff_t *f_ops){return 0; }loff_t chardevnode_llseek(struct file *file, loff_t offset, int ence){return 0; } struct file_operations my_fops = {.owner = THIS_MODULE,.open = chardevnode_open,.release = chardevnode_release,.unlocked_ioctl = chardevnode_ioctl,.read = chardevnode_read,.write = chardevnode_write,.llseek = chardevnode_llseek, };/*設(shè)備注冊到系統(tǒng)*/ static void reg_init_cdev(struct reg_dev *dev,int index){int err;int devno = MKDEV(numdev_major,numdev_minor+index);/*數(shù)據(jù)初始化*/cdev_init(&dev->cdev,&my_fops);dev->cdev.owner = THIS_MODULE;dev->cdev.ops = &my_fops;/*注冊到系統(tǒng)*/err = cdev_add(&dev->cdev,devno,1);if(err){printk(KERN_EMERG "cdev_add %d is fail! %d\n",index,err);}else{printk(KERN_EMERG "cdev_add %d is success!\n",numdev_minor+index);} }static int scdev_init(void) {int ret = 0,i;dev_t num_dev;printk(KERN_EMERG "numdev_major is %d!\n",numdev_major);printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor);if(numdev_major){num_dev = MKDEV(numdev_major,numdev_minor);ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME);}else{/*動態(tài)注冊設(shè)備號*/ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);/*獲得主設(shè)備號*/numdev_major = MAJOR(num_dev);printk(KERN_EMERG "adev_region req %d !\n",numdev_major);}if(ret<0){printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); }myclass = class_create(THIS_MODULE,DEVICE_NAME);my_devices = kmalloc(DEVICE_MINOR_NUM * sizeof(struct reg_dev),GFP_KERNEL);if(!my_devices){ret = -ENOMEM;goto fail;}memset(my_devices,0,DEVICE_MINOR_NUM * sizeof(struct reg_dev));/*設(shè)備初始化*/for(i=0;i<DEVICE_MINOR_NUM;i++){my_devices[i].data = kmalloc(REGDEV_SIZE,GFP_KERNEL);memset(my_devices[i].data,0,REGDEV_SIZE);/*設(shè)備注冊到系統(tǒng)*/reg_init_cdev(&my_devices[i],i);/*創(chuàng)建設(shè)備節(jié)點(diǎn)*/device_create(myclass,NULL,MKDEV(numdev_major,numdev_minor+i),NULL,DEVICE_NAME"%d",i);}printk(KERN_EMERG "scdev_init!\n");/*打印信息,KERN_EMERG表示緊急信息*/return 0;fail:/*注銷設(shè)備號*/unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);printk(KERN_EMERG "kmalloc is fail!\n");return ret; }static void scdev_exit(void) {int i;printk(KERN_EMERG "scdev_exit!\n");/*除去字符設(shè)備*/for(i=0;i<DEVICE_MINOR_NUM;i++){cdev_del(&(my_devices[i].cdev));/*摧毀設(shè)備節(jié)點(diǎn)函數(shù)d*/device_destroy(myclass,MKDEV(numdev_major,numdev_minor+i));}/*釋放設(shè)備class*/class_destroy(myclass);/*釋放內(nèi)存*/kfree(my_devices);unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM); }module_init(scdev_init); /*初始化函數(shù)*/ module_exit(scdev_exit); /*卸載函數(shù)*/二、Makefile
#!/bin/bash #通知編譯器我們要編譯模塊的哪些源碼 #這里是編譯itop4412_hello.c這個(gè)文件編譯成中間文件mini_linux_module.o obj-m += char_driver.o #源碼目錄變量,這里用戶需要根據(jù)實(shí)際情況選擇路徑 #作者是將Linux的源碼拷貝到目錄/home/topeet/android4.0下并解壓的 KDIR := /home/topeet/android4.0/iTop4412_Kernel_3.0#當(dāng)前目錄變量 PWD ?= $(shell pwd)#make命名默認(rèn)尋找第一個(gè)目標(biāo) #make -C就是指調(diào)用執(zhí)行的路徑 #$(KDIR)Linux源碼目錄,作者這里指的是/home/topeet/android4.0/iTop4412_Kernel_3.0 #$(PWD)當(dāng)前目錄變量 #modules要執(zhí)行的操作 all:make -C $(KDIR) M=$(PWD) modules#make clean執(zhí)行的操作是刪除后綴為o的文件 clean:rm -rf *.mod.c *.o *.order *.ko *.mod.o *.symvers三、應(yīng)用程序(invoke_char_driver.c)
“arm-none-linux-gnueabi-gcc -o invoke_char_driver invoke_char_driver.c -static”編譯應(yīng)用
#include <stdio.h>#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h>main(){int fd;char *hello_node0 = "/dev/chardevnode0";char *hello_node1 = "/dev/chardevnode1"; /*O_RDWR只讀打開,O_NDELAY非阻塞方式*/ if((fd = open(hello_node0,O_RDWR|O_NDELAY))<0){printf("APP open %s failed!\n",hello_node0);}else{printf("APP open %s success!\n",hello_node0);}close(fd);if((fd = open(hello_node1,O_RDWR|O_NDELAY))<0){printf("APP open %s failed!\n",hello_node1);}else{printf("APP open %s success!\n",hello_node1);}close(fd);}四、運(yùn)行
?
總結(jié)
以上是生活随笔為你收集整理的十六、字符驱动及应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 各版本arm-gcc区别与安装
- 下一篇: 十七、字符类 GPIOS