小松之LINUX 驱动学习笔记(二)
这两天一直在看字符驱动那块,后来从网上找啦几个例子,自己编译啦下,安装啥的都挺正常,就是用测试程序测试的时候总出问题,现在找到一个能测试的代码,自己先看看和原来的那个代码有啥不同,后面会继续更新,说下到底是啥问题导致驱动不能用。先附上能用代码的链接,这里先谢谢作者:
http://blog.chinaunix.net/uid-22666248-id-3052861.html
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h> #include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>//kmalloc
#include <linux/vmalloc.h>//vmalloc()
#include <linux/types.h>//ssize_t
#include <linux/fs.h>//file_operaiotns
#include <linux/uaccess.h>//copy_from_user #define MEM_MALLOC_SIZE 4096 ////缓冲区大小
#define MEM_MAJOR 240 ////主设备号
#define MEM_MINOR 0 char *mem_spvm = NULL; ////缓冲区指针,指向内存区
struct cdev *mem_cdev = NULL; //字符设备对象指针
struct class *mem_class = NULL; //设备类指针 static int __init mem_init(void);
static void __exit mem_exit(void);
static int mem_open(struct inode *inode,struct file *filp);
static int mem_release(struct inode *inode, struct file *filp);
static ssize_t mem_read(struct file *filp,char __user *buf,size_t count,loff_t *fpos);
static ssize_t mem_write(struct file *filp, char __user *buf,size_t count ,loff_t *fops); static const struct file_operations mem_fops={
.owner = THIS_MODULE,
.open = mem_open,
.release = mem_release,
.read = mem_read,
.write = mem_write,
}; static int __init mem_init(void)
{
int ret;
//创建设备号 主次设备号
int devno = MKDEV(MEM_MAJOR,MEM_MINOR);
printk("mem_init initial...\n"); //开辟内核内存缓冲区
mem_spvm = (char *)vmalloc(MEM_MALLOC_SIZE);
if(mem_spvm == NULL)
{
printk("vmalloc mem_spvm error\n");
return -ENOMEM;//
} //
mem_cdev = cdev_alloc();
if(mem_cdev == NULL)
{
printk("cdev_alloc error\n");
return -ENOMEM;
}
cdev_init(mem_cdev,&mem_fops);
mem_cdev->owner = THIS_MODULE;
ret = cdev_add(mem_cdev,devno,);//将字符设备键入内核系统
if(ret)
{
cdev_del(mem_cdev);
mem_cdev = NULL;
printk("cdev_add error\n");
return -;
} //
mem_class = class_create(THIS_MODULE,"ywx_class_char");
if(IS_ERR(mem_class))
{
printk("class_create error..\n");
return -;
}
device_create(mem_class,NULL,MKDEV(MEM_MAJOR,MEM_MINOR),NULL,"ywx_device_char"); printk("init finished..\n");
return ;
} static void __exit mem_exit(void)
{
printk("mem_exit starting..\n");
if(mem_cdev != NULL)
cdev_del(mem_cdev);
printk("cdev_del ok\n"); device_destroy(mem_class,MKDEV(MEM_MAJOR,MEM_MINOR));
class_destroy(mem_class); if(mem_spvm != NULL)
vfree(mem_spvm); printk("vfree ok\n");
printk("mem_exit finished..\n");
} static int mem_open(struct inode *inode,struct file *filp)
{
printk("open vmalloc space..\n");
try_module_get(THIS_MODULE);//模块引用计数器自加
printk("open vamlloc space ok..\n");
return ;
}
static int mem_release(struct inode *inode, struct file *filp)
{
printk("close vmalloc space..\n");
module_put(THIS_MODULE);//模块引用计数器自减
return ;
}
static ssize_t mem_read(struct file *filp,char __user *buf,size_t count,loff_t *fpos)
{
int ret = -;
char *tmp;
printk("copy data to the user space\n");
tmp = mem_spvm;
if(count > MEM_MALLOC_SIZE)
count = MEM_MALLOC_SIZE;
if(tmp != NULL)//将内核数据写入到用户空间
ret = copy_to_user(buf,tmp,count);
if(ret == )
{
printk("read copy data success\n");
return count;
}
else
{
printk("read copy data error\n");
return ;
}
}
static ssize_t mem_write(struct file *filp, char __user *buf,size_t count ,loff_t *fops)
{
int ret = -;
char *tmp;
printk("read data from the user space.\n");
tmp = mem_spvm;
if(count > MEM_MALLOC_SIZE)
count = MEM_MALLOC_SIZE;
if(tmp != NULL)
ret = copy_from_user(tmp,buf,count);
if(ret == )
{
printk("write copy data success.\n");
return count;
}
else
{
printk("write copy data error.\n");
return ;
}
} MODULE_LICENSE("GPL");
module_init(mem_init);
module_exit(mem_exit);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>//memset() int main(int argc, char *argv[])
{
int fd,cnt;
char buf[];
int i;
printf("char device testing..\n");
fd = open("/dev/ywx_device_char",O_RDWR);
if(fd == )
{
printf("open failed.\n");
return ;
} printf("input the data for kernel:");
scanf("%s",buf);
cnt = write(fd,buf,);
if(cnt == )
printf("write error\n"); printf("clear buf,and will read from kernel...\n");
for(i=;i<;i++)
buf[i] = ;//32 =" " cnt = read(fd,buf,);
if(cnt > )
printf("read data from kernel is:%s\n",buf);
else
printf("read data error\n");
close(fd);
printf("close app..\n");
return ;
}
运行的时候用root用户运行,可以看到/dev目录下有设备节点,然后运行test文件,可以看到能运行。
make;sudo insmod xxx.ko; sudo ./app
小松之LINUX 驱动学习笔记(二)的更多相关文章
- 小松之LINUX 驱动学习笔记(一)
本篇主要是讲解驱动开发的基础知识以及一些环境配置方面的问题. 下面是一个hello world的简单的模块代码,很简单./*********************** 模块的简单例子* author ...
- 小松之LINUX驱动学习笔记之模块间函数调用通讯
1. 符号导出函数 EXPORT_SYMBOL() EXPORT_SYMBOL标签内定义的函数对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用. EXPORT_SYMBOL_GPL( ...
- 小松之LINUX 驱动学习笔记(开篇)
时间对每个人都是公平的,就看你怎么对待他.每天多努力一点,未来就会轻松一点.作为一名北漂,感受着首都的压力,也曾萌生过逃离北上广的想法,但是,最后我最终还是选择留下来,随着年龄的增长,我已经没有那么多 ...
- linux 驱动学习笔记01--Linux 内核的编译
由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...
- Linux内核学习笔记二——进程
Linux内核学习笔记二——进程 一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...
- linux驱动学习(二) Makefile高级【转】
转自:http://blog.csdn.net/ghostyu/article/details/6866863 版权声明:本文为博主原创文章,未经博主允许不得转载. 在我前一篇写的[ linux驱动学 ...
- Linux 驱动学习笔记05--字符驱动实例,实现一个共享内存设备的驱动
断断续续学驱动,好不容易有空,做了段字符驱动的例子.主要还是跟书上学习在此记录下来,以后说不定能回过头来温故知新. 首先上驱动源码 gmem.c: /************************* ...
- linux 驱动学习笔记04--简单驱动
首先贴代码helloworld.c和Makefile /************************************************************************ ...
- linux 驱动学习笔记03--Linux 内核的引导
如图所示为 X86 PC 上从上电/复位到运行 Linux 用户空间初始进程的流程.在进入与 Linux相关代码之间,会经历如下阶段. ( 1 ) 当系统上电或复位时, CPU 会将 PC 指针赋值为 ...
随机推荐
- 安装Maven并搭建Maven私有仓库
一.说明 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具.我们在进行Java代码开发的时候,Eclipse+Maven+Jetty是一个十 ...
- iostat -x 1 查看磁盘的IO负载
Linux系统出现了性能问题.一般我们能够通过top.iostat,vmstat等命令来查看初步定位问题.当中iostat能够给我们提供丰富的IO状态数据 $ iostat -x -1 avg-cp ...
- Android Internet - WebView 的使用
WebView是Android 提供的操作网页的一个组件. 用于浏览网页及其它Internet资源. 这里总结了一些WebView 的经常使用接口.和2个小演示样例程序用于自己开发时直接使用.就不用再 ...
- Codeforces Round 313(div1)
A题: 题目大意: 给出内角全为120度的六边形的六条边的边长,求由多少边长为1的等边三角形构成. 解题思路: 将六边形补全为一个大的等边三角形,则大的等边三角形的边长为六边形的相邻三边之和,接着减去 ...
- POJ2228 Naptime 环形DP
题目大意:牛在第i个小时睡觉能够恢复U[i]点体力.睡觉时第一小时不恢复体力.一天的N小时连着下一天的1小时.求能够恢复体力的和的最大值. 定义DP[i][j][0]为前i个小时休息了j个小时,i小时 ...
- spring属性的三种注入方法
(1)使用set方法: public class Book { private String bookname;public void setBookname(String bookname) { ...
- ES Segment Memory——本质上就是segment中加到内存的FST数据,因此segment越多,该内存越大
ElasticSearch优化系列四:ES的heap是如何被瓜分掉的 转自:https://www.jianshu.com/p/f41b706db6c7 以下分别解读几个我知道的内存消耗大户: Seg ...
- 43.qt通过qss自定义外观
样式: 文件格式类型: candy.qss /* R1 */ QDialog { /*设置背景图片*/ background-image: url(:/images/background.png); ...
- expdp通过dblink远端导出
环境说明: db62是源端 rac数据库 dw03为需要导入的目标端数据库单机,实例名,服务名,字符串名都为dw03 数据库版本:11.2.0.4 操作系统:rehat 6.7 1.创建dblink ...
- ASP.NET Core Web API下事件驱动型架构的实现
mvp 原创博文:http://www.cnblogs.com/daxnet/p/8082694.html