不吃苦中苦,难为人上人。努力,给老婆孩子提供个良好的生活居住环境。

http://www.cnblogs.com/nan-jing/articles/5775038.html

这里提到。有这么多牛人。如果比得上人家。自古华山一条路,没别的招,不断的理解,不断的读,不断的写。哎。白了头。
阳痿早泄性无能,尿频尿急尿不净。钱不没挣多少。一身病。

上文可以完整的通过mknod创了设备节点。哪我如何知道设备号呢。
通过cat /proc/devices可以看到你创建设备的主设备号。好,没问题,可以读写了,哪我也没看到linux里有多少mknod啊。莫非是能自动创建设备节点? 哎,是的。可以在驱动代码里创建设备节点。

这句话不完全对。是可以在驱动里写代码。让用户空间的应用创建设备节点。哪个应用? 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 0x1

static int globalmem_major = 0;

struct globalmem_dev{
struct cdev cdev;
unsigned char mem[GLOBALMEM_SIZE];
};

struct globalmem_dev *globalmem_devp;

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了。

linux 驱动入门2的更多相关文章

  1. linux 驱动入门1

    世事艰难,人生不易. 夜深人静时候,回顾过去,往事历历在目.创南京,混苏州,下上海.都付出了巨大的努力.多少个不眠的夜晚,在冥思苦想.天生愚钝.又不是学计算机的.一直没较为深刻的理解 编程什么东西,一 ...

  2. linux 驱动入门4

    不吃苦中苦,难为人上人.努力,给老婆孩子提供个良好的生活居住环境.http://www.cnblogs.com/nan-jing/articles/5806399.html上文提到了如何创建proc节 ...

  3. linux 驱动入门3

    不吃苦中苦,难为人上人.努力,给老婆孩子提供个良好的生活居住环境. http://www.cnblogs.com/nan-jing/articles/5806399.html 上文提到.可以自动创建了 ...

  4. linux 驱动入门6

    看/sys目录经常看到bus device driver class. 这也是网上大量说的驱动驱动模型.这些的关系得熟悉得明白吧.是的.今天我先不整他们的关系.先逐个击破,然后再统一来理清楚他们之间的 ...

  5. linux 驱动入门5

    慢慢的开始转驱动,目前比较有时间,一定要把驱动学会.哎.人生慢慢路,一回头.已经工作了八九年了.努力.在买套房.改退休了.学驱动.个人认为首先要熟悉驱动框架.慢慢来.心急吃不了热豆腐. 看网上都说的设 ...

  6. Linux驱动入门——构建和运行模块

    Hello world模块 本文介绍如何向内核中添加一个hello模块.该模块的功能是在模块加载时,向系统日志输出"hello world\n" 在模块卸载时输出"Goo ...

  7. Linux FC/iSCSI存储设备管理系列(一):Linux系统设备驱动入门

    Linux FC/iSCSI存储设备管理系列(一):Linux系统设备驱动入门 转载请在文首保留原文出处:EMC中文支持论坛 - https://community.emc.com/go/chines ...

  8. IT技术学习指导之Linux系统入门的4个阶段(纯干货带图)

    IT技术学习指导之Linux系统入门的4个阶段(纯干货带图) 全世界60%的人都在使用Linux.几乎没有人没有受到Linux系统的"恩惠",我们享受的大量服务(包括网页服务.聊天 ...

  9. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

随机推荐

  1. 超棒的自定义超酷滚动条jQuery插件 - Perfect Scrollbar

    可能大家厌倦了千篇一律的页面滚动条,如果你希望能够设计出与众不同的页面UI设计的话,Perfect ScrollBar可能就是你寻找的解决方案. 这个滚动条来自于一个个人项目,一个简单但是非常棒的滚动 ...

  2. 织梦DEDE文章列表前面自动加递增数字标签

    实现的办法很简单,只须要在序号递增的处所加上这段代码就行 [field:global runphp=""yes"" name=autoindex][/field ...

  3. UVA 10308 Roads in the North

    input u1 v1 w1 u2 v2 w2 ... un vn wn 1<=vi,ui<=n+1 /n output 距离最远的两个点的距离 做法:一颗全连通且只有一条路从一个顶点到达 ...

  4. phpmyadmin配置方式

    简单的说,phpmyadmin就是一种mysql的管理工具,安装该工具后,即可以通过web形式直接管理mysql数据,而不需要通过执行系统命令来管理,非常适合对数据库操作命令不熟悉的数据库管理者,下面 ...

  5. 用PHP与XML进行网站编程

    一.小序 HTML简单易学又通用,一般的PHP程序就是嵌入在HTML语言之中实现的.但是随着WEB越来越广泛的应用,HTML的弱点也越来越明显了.XML的出现,弥补了这些不足,它提供了一个能够处理互联 ...

  6. Core Data & MagicalRecord

    iOS 本地数据持久化存储: 1.plist 2.归档 3.NSUserDefaults 4.NSFileManager 5.数据库 一.CoreData概述 CoreData是苹果自带的管理数据库的 ...

  7. hadoop yarn 易理解

    Hadoop 和 MRv1 简单介绍 Hadoop 集群可从单一节点(其中所有 Hadoop 实体都在同一个节点上运行)扩展到数千个节点(其中的功能分散在各个节点之间,以增加并行处理活动).图 1 演 ...

  8. Mie散射 文献图片

    Technorati 标签: Mie Scattering,遥感,Remote Sensing

  9. L4,an exciting trip

    expressions: a great number of 许多 in the centre of 在…的中部 sentences: I have just had breakfast. I hav ...

  10. angular实现select的ng-options

    html <div ng-controller="ngSelect"> <select ng-model="vm.selectVal" ng- ...