在ubuntu下编写验证字符设备驱动

并移植到arm开发板上

1,准备工作

  1.   uname -r  查看电脑版本信息
  2. 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

解决驱动卸载问题

最新文章

  1. 【BZOJ-1123】BLO Tarjan 点双连通分量
  2. (一)Nand FLASH 原理讲解
  3. 自定义Java集合
  4. Java api 入门教程 之 JAVA的包装类
  5. Adobe Reader &amp; PDF 护眼设置
  6. 【翻译十四】java-并发之保护块儿
  7. 形行色色的下拉菜单(HTML/CSS JS方法 jQuery方法实现)
  8. JS 之作用域链和闭包
  9. dede织梦列表页如何调用全站子栏目
  10. linux查看端口信息以及关闭进程
  11. hadoop No FileSystem for scheme: hdfs
  12. 通知中心 NSNotificationCenter
  13. mysql-5.7.12-winx64.zip Windows (x86, 64-bit), ZIP Archive版免安装配置
  14. Spring集成Quartz定时器
  15. material design是什么?(待以后学习)
  16. 第一百二十四节,JavaScriptCookie与存储
  17. .net 使用oracle 的存储过程有返回值也有数据集(游标)
  18. GYM 101673 A - Abstract Art 多个一般多边形面积并
  19. Mysql学习笔记之常用数据类型
  20. ASLR/DEP绕过技术概览

热门文章

  1. 事件&amp;表达式
  2. WordPress版微信小程序3.2版发布
  3. 逆向工程vgenerator(二)
  4. 【JsonView工具】谷歌浏览器中安装JsonView扩展程序
  5. Struts2高位漏洞升级到struts2.3.32
  6. pgsql 常用命令
  7. mysql 数据插入时的问题
  8. Vue组件间传值 v-model
  9. Spring中@Value注解使用——一种新的直接读取配置文件的方式
  10. React条件渲染