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

编程什么东西,一直没有入门。

感谢Qisda, 让我在08年就开始接触android. 都不容易。

编程是什么?

编程是数据处理。如何处理? cpu通过指令指针的跳转,实现了读下一条指令,cpu实现了读指令,编译指令。

感谢marvell. 哎marvell技术 不可谓不强。认识一大批牛人。jialin, jiaguo, xinjiang wenzhao fuqiang ruikuang xia . 哎,我们一个team。我是最菜的。一个上海交大,一个武大,一个哈工大。一个南大。
一个中国科大少年班。南航和他们比太菜了。哎。 就不断的琢磨。

还是老套路把。先从简单字符驱动开始。

驱动是为了沟通os和硬件。起到了承上启下的作用。哪就说明这个模块就能让os认识它。有能操作硬件。

那如何让os认识它呢?

就一句话int cdev_add(struct cdev *p, dev_t dev, unsigned count).
那这些参数哪来的呢?

struct cdev就需要自己创建结构体内存。 dev_t是分配的设备号。

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

这样就创建了这个结构体。初始化时候分配内存就好了。为什么要弄个结构体。弄个静态全局变量可以吗? 也可以的 。但是不太方便。为什么不方便呢? 下面说

还要分配设备号
if (globalmem_major){
result = register_chrdev_region(devno, 2, "globalmem");
}else {
result = alloc_chrdev_region(&devno,0, 2, "globalmem");
globalmem_major = MAJOR(devno);
}
有了cdev dev_t. 就可以添加到os了。

为什么参数要有个设备号呢? 系统有很多的驱动,应用程序只看到设备节点。当应用open的时候,系统会看大这个设备的设备号。根据设备号找对应的驱动。所以add的时候需要跟上设备号。

cdev初始化还要加上fop。
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,
};

当应用call open的时候,操作系统会先做一些通用的处理。做什么通用的处理我也不清楚,正在学习,不知道就不知道。千万别像书上写的。这里一般用不到。不必了解。不了解中国人怎么写出操作系统来?

做通用处理的时候会产生inode file两个结构体。 同时把file的fop的控件用驱动的add的cdev里的fop初始化。哪肯定的,不然以后read write时候参数都有file指针,那系统如何找到我们驱动的真正的read write
实现呢?

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;
}
dev = container_of(inode->i_cdev, struct globalmem_dev, cdev);
filp->private_data = dev;
这两句话看清楚了吗? 使劲理解。

下面把我的测试代码发出来把
#include<linux/module.h>
#include <linux/types.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>

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;

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!");
//marvell 臧春杰
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){
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;
//marvell 臧春杰
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;
//marvell 臧春杰
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; //marvell 臧春杰
err = cdev_add(&dev->cdev, devno, 1);
if (err){
printk(KERN_ALERT"cdev_add failed!");
}
}

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;
}

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);
//marvell 臧春杰
globalmem_setup_cdev(&globalmem_devp[1], 1);

return 0;

fail_malloc:
//marvell 臧春杰
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);
}

module_param(globalmem_major, int, S_IRUGO);
module_init(globalmem_init);
module_exit(globalmem_exit);

这个代码我在ubuntu16.04上编译测试过。

结果如下

[ 443.797578] major-------------->247
[ 593.833449] globalmem_open!
[ 593.833486] write 13 bytes from 0
[ 593.833499] globalmem_release!
[ 620.507565] globalmem_open!
[ 620.507659] read 4096 bytes from 0
[ 620.509053] globalmem_release!
[ 647.025424] globalmem_open!
[ 647.025465] write 16 bytes from 0
[ 647.025475] globalmem_release!
[ 650.531294] globalmem_open!
[ 650.531327] read 4096 bytes from 0

可以直接拷贝,写个makefile编译,后续我再加点自动创建设备节点。就不用自己mknod了。

不吃苦中苦,难为人上人。千万别成王宝强。

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

  1. linux 驱动入门4

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

  2. linux 驱动入门3

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

  3. linux 驱动入门2

    不吃苦中苦,难为人上人.努力,给老婆孩子提供个良好的生活居住环境. http://www.cnblogs.com/nan-jing/articles/5775038.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. 关于C#静态构造函数的几点说明

    静态构造函数是C#的一个新特性,其实好像很少用到.不过当我们想初始化一些静态变量的时候就需要用到它了.这个构造函数是属于类的,而不是属于哪里实例的,就是说这个构造函数只会被执行一次.也就是在创建第一个 ...

  2. OpenGL---------BMP文件格式

    计算机保存图象的方法通常有两种:一是“矢量图”,一是“像素图”.矢量图保存了图象中每一几何物体的位置.形状.大小等信息,在显示图象时,根据这些信息计算得到完整的图象.“像素图”是将完整的图象纵横分为若 ...

  3. 过滤器HttpModule

    1.建一个类库文件  FirsModule,实现IHttpModule接口,实现其中的两个方法,写一函数实现自己的代码逻辑,在Init方法中调用即可. // <summary> /// 第 ...

  4. Apache + PHP in Windows XP (to add SQLite)

    Firstly, Winxp do not support VC11+, so choose Apache packs compiled under VC10-. Before installatio ...

  5. 视频 -> 帧 浅析

    原创:转载请注明出处 关于帧率 首先以下几个概念必须弄清楚 1.一个帧就是一个画面 2.视频有无数个帧组成 3.表达时间的量  CMTime 的定义: typedef struct { CMTimeV ...

  6. GameUnity 2.0 发布倒计时

    万众期待的 gameunity 网络游戏框架 已经完成了,现在在最后的检验调试阶段. 因为版本 改动非常之大,所以 版本号 从0.2版本 改成 2.0版本. gameunity事件部分,一如既往保持高 ...

  7. html 7.29

    4.请判断以下说法是否正确:HTML 会被 XHTML 取代. 您的回答:错误 正确答案:正确 9.请判断以下说法是否正确:DOCTYPE 没有关闭标签. 您的回答:错误 正确答案:正确 13.下列哪 ...

  8. POJ3468--A Simple Problem with Integers--线段树/树状数组 改段求段

    题目描述 You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type ...

  9. c++ 中bool 的默认值

    比如在Test.h中定义变量: _isFirst; //Test.h头文件 #ifndef __TEST_H__ #define __TEST_H__ class Test{ private: boo ...

  10. ThinkPHP 框架执行流程分析

    总体来说,应用的流程涉及到几个文件:Index.phpThinkPHP.phpThink.class.phpApp.class.phpDispatcher.class.phpThinkPHP/Mode ...