#
#
#
#
#
#
#
#
#
#
#
#“演示.h”
(“fgj”);
(“双 BSD/GPL”);
//很郁闷的是,即使移植到开发板上,还是说这个驱动污染了内核。
*;
//声明自己定义的设备结构体的指针
字符=0;
//统计并记录该设备被打开的次数
u8[256];
//内核中的数据结构和数据类型真是奇怪。 这个u8确实让人费解。 结果是一个无符号的8位数据类型。
//
int(索引节点*索引节点,文件*filp)
*开发;
//只允许设备打开一次
如果(>0)-;
++;
/* 宏通过结构体中的变量获取结构体本身的指针
%CE%DA%D1%BB%C3%F7/blog/item/ade3.html
太高级了,我看不懂。
*/
dev = (inode->, , cdev);
filp-> = dev;
0;
int(索引节点*索引节点,文件*filp)
--;
0;
(文件*filp,字符*buf,计数,*f_pos)
整数;
位置=*f_位置; /* 文件的读写位置*/
如果(位置>=256)
=0;
转到出去;
if(计数>(256-位置))
计数=256位;
pos += 计数;
if ((buf,+*f_pos,计数))
计数=-; /* 向应用程序空间写入数据*/
转到出去;
*f_pos = pos; /* 改变文件的读写位置 */
出去:
数数;
(文件 *filp,const char *buf,计数,*f_pos)
=-; /* “goto out” 中使用的值 */
位置=*f_位置;
如果(位置>=256)
转到出去;
//如果要写入的输入大于剩余内存空间,则只写入剩余空间,防止溢出。
if(计数>(256-位置))
计数=256位;
//如果C语言扎实的话,剩下的代码不难理解。 抱歉我的表达能力不好。
pos += 计数;
// 原文说的是复制数据到用户空间。 我认为它应该将数据复制到内核空间。 这应该是作者的笔误。 没什么大不了的。
if ((+*f_pos, buf, 计数)) {
=-;
转到出去;
*f_pos = pos;
数数;
出去:
;
/*这几天我才粗略了解了ioctl的作用。 ioctl 用于控制设备。 int cmd 是发送到设备的命令。
ioctl()可能是Linux中最复杂的函数*/
int(inode *inode,文件*filp,int cmd,长arg)
如果(cmd==)
(“ioctl /n”);
0;
如果(cmd==)
(“ioctl /n”);
0;
(“ioctl错误/n”);
-;
// 为了实现随机访问,这段代码应该是一个无符号整数来记录文件指针偏移量。 参考用户态的seek()就不难理解了。
(文件*filp,关闭,int)
位置;
pos = filp->f_pos;
()
案例0:
位置=关闭;
休息;
情况1:
pos += 关闭;
休息;
案例2:
:
-;
如果 ((pos>256) || (pos {
-;
filp->f_pos=pos;
//这个结构体非常重要,我们需要了解它的作用
= {
.所有者 = ,
。 = ,
.读=,
.写=,
.ioctl = ,
.打开=,
。 = ,
};
/******************************************************** ***** *****
****************************************************** * *****/
无效(无效)
//下面入口函数讲MKDEV
dev_t devno = MKDEV(, );
如果()
(&->cdev);
//内核下的内存操作函数确实很奇怪,习惯就好
kfree();
//调用gion()函数释放一系列分配的设备号
祗园(devno,1);
整数(空)
整数;
// 在内核中,dev_t类型(定义于)用于保存设备号——包括主设备号和次设备号
dev_t dev = 0;
/*内核中定义了三个宏来处理主次设备号:MAJOR和MINOR宏可以从16位数字中提取主次设备号,MKDEV宏可以将主次设备号组合成16位数字数字。 。
高8位用于主设备号,低8位用于次设备号。
%E7%AC%AC%E5%8D%81%E4%B8%80%E7%AB%A0%20%20%E8%AE%BE%E5%A4%87%E9%A9%B1%E5%8A %A8%E7%A8%8B%E5%BA%8F/11.2.3.htm*/
dev = MKDEV(, );
/*获取一个或多个要使用的设备号
如果分配成功,on的返回值为0。如果分配错误,则返回负的错误码,并且无法访问所请求的区域。 */
= on(dev, 1, "演示");
如果(<0)
(“DEMO: 无法获取主要%d/n”,);
;
//为自定义设备结构申请空间
= (( ), );
如果 (!)
=-;
走向失败;
//清除新申请的空间。 我的水平只能理解这些简单的功能。
(, 0, ( ));
//初始化字符驱动程序。 我不明白这一点。 我只能做一个粗略的猜测。
//而且,一旦理解了这个结构体的功能,你就会明白为什么Linux驱动只需要实现很少的驱动。
(&->cdev, &);
->cdev.owner = ;
->cdev.ops = &;
//将字符驱动添加到内核中
= (&->cdev, dev, 1);
如果()
(“错误%d演示/n”,);
走向失败;
0;
失败:
//如果失败,调用exit函数并擦除pp。
();
;
//这两个是内核驱动指示程序进入和退出所必需的。
();
();
demo.c 文件结尾
我还不知道如何编写make文件。 我使用构建内核项目来编译该驱动程序。
下面用于编译ko文件并移植到arm9开发板()
AR=ar
ARCH = 手臂
CC = ARM-Linux-GCC
+= $() -墙
+= -I$()
= - -rpath-link /usr/local/arm/3.4.1/lib/gcc/arm-linux/3.4.1
ifneq ($(),)
obj-m:= demo-.o #模块名称
别的
KDIR:= /root/linux-2.6.12
PWD:= $(shell 密码)
:
$(MAKE) -C $(KDIR) =$(PWD)
万一
加载驱动程序
# 演示.ko
然后使用lsmod或者cat /proc/检查驱动是否加载
# mknod /dev/fgj c 224 0 创建设备节点
然后你可以使用下面的代码来测试驱动程序
/*
* 此文件符合 GNU 的条款和
*。 请参阅此文件的主要部分“”
* 了解更多。