tiny4412--linux驱动学习(2)
在ubuntu下编写验证字符设备驱动
并移植到arm开发板上
1,准备工作
- uname -r 查看电脑版本信息
- apt-get install linux-source 安装相应版本的linux内核
2,编写驱动程序
Global CharDev.c
/* GlobalCharDev.c */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h> #include <asm/uaccess.h> #define DEV_NAME "GlobalChar" static ssize_t GlobalRead(struct file *, char *, size_t, loff_t *);
static ssize_t GlobalWrite(struct file *, const char *, size_t,loff_t *); static int char_major = ;
static int GlobalData = ; /* "GlobalChar"设备的全局变量 */ /* 初始化字符设备驱动的 file_operations 结构体 */
struct file_operations globalchar_fops =
{
.read = GlobalRead,
.write = GlobalWrite
}; /* 模块初始化 */
static int __init GlobalChar_init(void)
{
int ret; ret = register_chrdev(char_major, DEV_NAME, &globalchar_fops);/* 注册设备驱动,_driver_char_misc.c 第290行参考 */
if(ret < )
printk(KERN_ALERT "GlobalChar Reg Fail\n");
else
{
printk(KERN_ALERT "GlobalChar Reg Success\n");
char_major = ret;
printk(KERN_ALERT "Major = %d\n", char_major);
}
return ret;
} /* 模块卸载函数 */
static void __exit GlobalChar_exit(void)
{
unregister_chrdev(char_major, DEV_NAME); /* 注销设备驱动 */
return;
} /* 模块驱动读函数 */
static ssize_t GlobalRead(struct file *file, char *buf, size_t len, loff_t *off)
{
if (copy_to_user(buf, &GlobalData ,sizeof(int)))
{
/* 从内核复制 GlobalData 到用户空间*/
return -EFAULT;
}
return sizeof(int);
}
/* 模块驱动写函数 */
static ssize_t GlobalWrite(struct file *file, const char *buf, size_t len, loff_t *off)
{
if (copy_from_user(&GlobalData, buf, sizeof(int)))
{
/* 从用户复制 GlobalData 到内核 */
return -EFAULT;
}
return sizeof(int);
} module_init(GlobalChar_init);
module_exit(GlobalChar_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("dongjin");
Makefile
ifneq ($(KERNELRELEASE),)
obj-m := GlobalCharDev.o
else # KERNELDIR ?= /lib/modules/$(shell uname -r)/build
KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r) //这两个都可以 PWD := $(shell pwd) default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean:
rm -rf rm -rf *.ko *.mod* *.o* *.sy*
endif
理解:
pwd--> 驱动文件目录
kerneldir --> 内核源码目录
default --> 表示到内核源码目录中去编译pwd下的驱动文件
——————————————————————————————————————————————————————
make 编译
root@ubuntu:/home/arm/data/char_driver# make
make -C /usr/src/linux-headers-4.4.--generic M=/home/arm/data/char_driver modules
make[]: 正在进入目录 `/usr/src/linux-headers-4.4.--generic'
CC [M] /home/arm/data/char_driver/GlobalCharDev.o
Building modules, stage .
MODPOST modules
LD [M] /home/arm/data/char_driver/GlobalCharDev.ko
make[]:正在离开目录 `/usr/src/linux-headers-4.4.--generic'
出现Global CharDev.ko文件
2,insmod Global CharDev.ko 将模块加入内核
3,cat /proc/devices 查看驱动设备
4,mknod /dev/GlobalChar c 247 0 根据相应的设备号,建立设备节点。
5,测试文件
/* GlobaiCharText.c 测试文件*/ #include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h> #define DEV_NAME "/dev/GlobalChar" int main()
{
int fd, num; /* 打开设备文件 */
fd = open(DEV_NAME, O_RDWR, S_IRUSR | S_IWUSR);
if(fd < )
{
printf("Open Device Fail!\n");
return -;
} /* 读取当前设备数值 */
read(fd, &num, sizeof(int));
printf("The GlobalChar is %d\n", num); printf("Please input a numble written to GlobalChar: ");
scanf("%d", &num); /* 写入新的数值 */
write(fd, &num, sizeof(int)); /* 重新读取数值 */
read(fd, &num, sizeof(int));
printf("The GlobalChar is %d\n", num); close(fd);
return ; }
gcc -o GlobalCharText GlobalCharText.c 编译出可执行文件
执行:
root@ubuntu:/home/arm/data/char_driver# ./a.out
The GlobalChar is
Please input a numble written to GlobalChar:
The GlobalChar is
——————————————————————————————————————————————————————————————————————
通过NFS我们可以建立共享目录,将编写好的驱动加载到arm板,当然也需要配置环境变量。
1,驱动文件:需要将Make file中KERNLDIR 改成 自己下载内核的地址,如:
KERNELDIR ?= /home/arm/linux-4.4
2,测试文件:理所当然我们需要使用交叉编译去编译出可执行文件。
注意:首先我们要知道自己制作的做小系统是采用静态编译还是动态编译,我的采用静态编译
1,静态:
2,动态:
需要在制作最小系统时,在 /lib 下加入所需的动态交叉编译库(所选交叉编译工具目录下的链接库),但是我在制作randisk的过程中,提示内存不足,暂没查找其原因。
如果在静态根文件系统内使用动态编译链所编译的elf,会提示:-sh:./test:no found (这里 not found 指的是 链接库)
测试:
卸载:
1,删除 /dev 下的设备节点
rm /dev/GlobalChar
2,卸载驱动
rmmod GlopbalCharDev.ko
出现问题:
——————————————————————————————————————————————————————
参考:
http://tieba.baidu.com/p/3645403366
https://blog.csdn.net/Ultraman_hs/article/details/53239455
解决移植到arm上不兼容的问题
https://blog.csdn.net/zqj6893/article/details/48439711
解决驱动卸载问题
tiny4412--linux驱动学习(2)的更多相关文章
- linux 驱动学习笔记01--Linux 内核的编译
由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...
- linux驱动学习(二) Makefile高级【转】
转自:http://blog.csdn.net/ghostyu/article/details/6866863 版权声明:本文为博主原创文章,未经博主允许不得转载. 在我前一篇写的[ linux驱动学 ...
- Linux驱动学习步骤(转载)
1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, ls ...
- 树莓派linux驱动学习之hello world
最近想学习一下linux驱动,看了一些书和教学视频,大概了解了一下,不过要想深入,肯定需要实践.手上有几块linux的板子,最终选择了树莓派作为我的实验平台,资料比较丰富,接口也比较简单. 程序员的入 ...
- Linux驱动学习1.hello world;
最近项目需要使用Linux系统开发,借此机会学习一下Linux驱动开发 hello word代码hello.c #include <linux/module.h> #include < ...
- 【Linux驱动学习】SD卡规范学习
摘要: 学习SD卡的相关规范,包括定义,硬件特性,数据传输,命令系统等.不涉及代码. 文章针对Linux驱动开发而写,以助于理解SD卡驱动,不会涉及过多硬件内容. 纲要: 1. SD卡介绍 2. SD ...
- linux驱动学习_1
目前项目需要,需要做linux驱动了,记录一下 学习驱动,大家一定都会写一个hello world代码,网上也有很多范例,但是记录一下遇到的问题. 1.make之后,使用insmod加载,终端没有打印 ...
- Linux驱动学习之常用的模块操作命令
1.常用的模块操作命令 (1)lsmod(list module,将模块列表显示),功能是打印出当前内核中已经安装的模块列表 (2)insmod(install module,安装模块),功能是向当前 ...
- Linux驱动学习之驱动开发准备工作
一.开启驱动开发之路 1.驱动开发的准备工作 (1)正常运行linux系统的开发板.要求开发板中的linux的zImage必须是自己编译的,不能是别人编译的.原因在于在安装模块的时候会进行安全性校验 ...
- Linux驱动学习之什么是驱动?
一.什么是驱动? 1: 驱动一词的字面意思 2: 物理上的驱动 3: 硬件中的驱动 4: linux内核驱动.软件层面上的驱动广义上是指:这一段代码操作了硬件去动,所以这一段代码就叫硬件的驱动程序. ...
随机推荐
- var let const
你真的永远都不用var了吗? javascript的一些争论已经浮现出了一些经典的案例,因此,es6的拥护者你们应该讲var遗忘吗?这篇博客将带你走进被遗忘的角落 首先举例反对者的几个观点: 1.如果 ...
- 爬虫——BeautifulSoup和Xpath
爬虫我们大概可以分为三部分:爬取——>解析——>存储 一 Beautiful Soup: Beautiful Soup提供一些简单的.python式的函数用来处理导航.搜索.修改分析树等功 ...
- 如何简单理解js中this的指向
前序 每个人学js都会被this指向这个东西搞得很蒙,那就是this的指向问题.首先,我们要明白 this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上thi ...
- net.sf.json
JSONObject package com.itlwc.test; import net.sf.json.JSONArray; import net.sf.json.JSONO ...
- 团队作业-Week9-软件项目的风险
一.软件项目中的风险 软件项目的风险无非体现在以下四个方面:需求.技术.成本和进度.IT项目开发中常见的风险有如下几类: (1)需求风险 ①需求已经成为项目基准,但需求还在继续变化: ②需求定义欠佳, ...
- 稀疏矩阵 part 5
▶ 目前为止能跑的所有代码及其结果(2019年2月24日),之后添加:DIA 乘法 GPU 版:其他维度的乘法(矩阵乘矩阵):其他稀疏矩阵格式之间的相互转化 #include <stdio.h& ...
- Maven 错误 :The POM for com.xxx:jar:0.0.1-SNAPSHOT is invalid, transitive dependencies (if any) will not be available
一个大的maven 项目,结构是一个根pom,下面几个小的module,包括了appservice-darc,appservice-entity等,其中appservice-darc 依赖了 apps ...
- 学习Flask框架
# -*- encoding: utf-8 -*- #导包 from flask import Flask #建立flask对象 app = Flask(__name__) #使用flask路由器 ...
- sqlserver2012 数据库差异备份恢复 记录
sqlserver2012恢复过程: 先恢复全备份,再恢复差异,注意:勾选NoRecovery选项. 恢复完成后,出现: Sqlserver数据库 一直显示“正在还原…” 的状态. 引用:http:/ ...
- sqlserver 存储过程返回游标的处理
创建表: create table tb1( id int , name ) ) ------------------------------------------------- 创建返回游标的存储 ...