不吃苦中苦,難爲人上人。努力,給老婆孩子提供個良好的生活居住環境。html
http://www.cnblogs.com/nan-jing/articles/5775038.htmlnode
這裏提到。有這麼多牛人。若是比得上人家。自古華山一條路,沒別的招,不斷的理解,不斷的讀,不斷的寫。哎。白了頭。
陽痿早泄性無能,尿頻尿急尿不淨。錢不沒掙多少。一身病。linux
上文能夠完整的經過mknod創了設備節點。哪我如何知道設備號呢。
經過cat /proc/devices能夠看到你建立設備的主設備號。好,沒問題,能夠讀寫了,哪我也沒看到linux裏有多少mknod啊。莫非是能自動建立設備節點? 哎,是的。能夠在驅動代碼裏建立設備節點。ubuntu
這句話不徹底對。是能夠在驅動裏寫代碼。讓用戶空間的應用建立設備節點。哪一個應用? mdev. 哪我如何通知mdev建立設備節點呢?
用着兩句
class_create();
device_create();
注意測試環境,個人環境virtualbox + ubuntu16.04
好了。看代碼。把上面的代碼修改下。具體就修改一個函數就行了。
下面把個人測試代碼發出來把
#include<linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
//#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/device.h>函數
MODULE_AUTHOR("qcom.shanghai@gmail.com");
MODULE_LICENSE("Dual BSD/GPL");測試
#define GLOBALMEM_SIZE 0X1000
#define MEM_CLEAR 0x1spa
static int globalmem_major = 0;htm
struct globalmem_dev{
struct cdev cdev;
unsigned char mem[GLOBALMEM_SIZE];
};blog
struct globalmem_dev *globalmem_devp;ip
struct class *globalmem_class;
static int globalmem_open(struct inode *inode, struct file *filp){
struct globalmem_dev *dev;
dev = container_of(inode->i_cdev, struct globalmem_dev, cdev);
filp->private_data = dev;
printk(KERN_ALERT "globalmem_open!");
return 0;
}
static int globalmem_release(struct inode *inode, struct file *filp){
printk(KERN_ALERT "globalmem_release!");
return 0;
}
static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos){
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalmem_dev *dev = filp->private_data;
if (p >= GLOBALMEM_SIZE){
return 0;
}
if (count > GLOBALMEM_SIZE - p){
//honeywell 臧春傑
count = GLOBALMEM_SIZE - p;
}
if (copy_to_user(buf, (void *)(dev->mem + p), count)){
ret = - EFAULT;
}else {
*ppos += count;
ret = count;
printk(KERN_ALERT "read %u bytes from %lu \n", count, p);
}
return ret;
}
static ssize_t globalmem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos){
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalmem_dev *dev = filp->private_data;
if (p >= GLOBALMEM_SIZE){
return 0;
}
if (count > GLOBALMEM_SIZE - p){
count = GLOBALMEM_SIZE - p;
}
if (copy_from_user(dev->mem + p, buf, count)){
ret = - EFAULT;
}else {
*ppos += count;
ret = count;
printk(KERN_ALERT "write %u bytes from %lu \n", count, p);
}
return ret;
}
static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig){
loff_t ret = 0;
switch(orig){
case 0:
if (offset < 0){
ret = - EFAULT;
break;
}
if ((unsigned int)offset > GLOBALMEM_SIZE){
ret = - EFAULT;
break;
}
filp->f_pos = (unsigned int) offset;
ret = filp->f_pos;
break;
case 1:
if ((filp->f_pos + offset) > GLOBALMEM_SIZE){
ret = - EFAULT;
break;
}
if ((filp->f_pos + offset) < 0){
ret = - EFAULT;
break;
}
filp->f_pos += offset;
ret = filp->f_pos;
break;
default:
ret = - EFAULT;
break;
}
return ret;
}
static long globalmem_ioctl(struct file *flip, unsigned int cmd, unsigned long arg){
printk(KERN_ALERT "globalmem_ioctl");
return 10L;
}
static const struct file_operations globalmem_fops = {
.owner = THIS_MODULE,
.llseek = globalmem_llseek,
.read = globalmem_read,
.write = globalmem_write,
.unlocked_ioctl = globalmem_ioctl,
.open = globalmem_open,
.release = globalmem_release,
};
static void globalmem_setup_cdev(struct globalmem_dev *dev, int index){
int err, devno = MKDEV(globalmem_major, index);
cdev_init(&(dev->cdev), &globalmem_fops);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if (err){
printk(KERN_ALERT"cdev_add failed!");
}
}
//honeywell 臧春傑
static void create_dev_node(int index){
device_create(globalmem_class, NULL, MKDEV(globalmem_major, index), NULL, "globalmem_cj1");
//honeywell 臧春傑
device_create(globalmem_class, NULL, MKDEV(globalmem_major, index + 1), NULL, "globalmem_cj2");
}
static int __init globalmem_init(void){
int result;
dev_t devno = MKDEV(globalmem_major, 0);
if (globalmem_major){
result = register_chrdev_region(devno, 2, "globalmem");
}else {
result = alloc_chrdev_region(&devno,0, 2, "globalmem");
globalmem_major = MAJOR(devno);
}
printk(KERN_ALERT "major-------------->%d \n", globalmem_major);
if (result < 0){
return result;
}
//honeywell 臧春傑
globalmem_class = class_create(THIS_MODULE, "globalmem_cls");
create_dev_node(0);
globalmem_devp = kmalloc(2 * sizeof(struct globalmem_dev), GFP_KERNEL);
if (! globalmem_devp){
result = -ENOMEM;
goto fail_malloc;
}
memset(globalmem_devp, 0, 2 * sizeof(struct globalmem_dev));
globalmem_setup_cdev(&globalmem_devp[0], 0);
globalmem_setup_cdev(&globalmem_devp[1], 1);
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
}
static void __exit globalmem_exit(void){
cdev_del(&globalmem_devp[0].cdev);
cdev_del(&globalmem_devp[1].cdev);
kfree(globalmem_devp);
unregister_chrdev_region(MKDEV(globalmem_major, 0), 2);
class_destroy(globalmem_class);
}
module_param(globalmem_major, int, S_IRUGO);
//honeywell 臧春傑
module_init(globalmem_init);
module_exit(globalmem_exit);
這個代碼我在ubuntu16.04上編譯測試過。
結果以下
ubuntu@ubuntu-VirtualBox:~/driver/test3$ ls -l /dev/ | grep global
crw------- 1 root root 247, 0 8月 25 13:14 globalmem_cj1
crw------- 1 root root 247, 1 8月 25 13:14 globalmem_cj2
能夠直接拷貝,寫個makefile編譯,後續我再加點自動建立設備節點。就不用本身mknod了。