IMX257实现Ramblock驱动程序编写

2024-08-13  

今天,我们再内存中申请一片内存,模拟作为块设备,程序如下:


程序一:简单的一个小程序


1.定义gendisk结构体与request_queue请求队列结构体,以及file-operation结构体

gendisk结构体,主要是用于定义与内核,硬件有关的一些重要信息,还有就是,告诉内核定义请求队列的结构体以及操作函数的结构体。


请求队列:主要是提供读写能力,实现读写请求的存储,然后自己调用do_rambloc_request函数来实现读写操作。


操作函数:如字符设备的操作函数一样,不过此处的操作函数暂时不需定义任何函数,但是必须要有.MODULE属性,否则会报错


2.入口函数实现

如图所示,在入口函数中主要包含了以下几个操作。


1):分般gendisk结构体,并且设备此设备个数为16个


2):分配、初始化队列,并且指定队列读写函数do_ramblock_request函数。


3):设置以下虚拟块设备的一些属性,包括主设备号,次设备号,名字,操作函数,队列,设备容量等。

4):最后就是注册gendisk结构体。


3.读写函数实现


一些都准备就绪之后,当用户对虚拟块设备发出请求时,系统会调用读写函数do_ramblock_request来实现读写功能。但是刚开始,还是简单点,所以此处,我们的函数主要的功能就是打印信息,告诉我们是否进入了这个读写函数。

4.出口函数实现


和入口函数相反,出口函数主要负责的就是释放前面申请的内存,反注册前面注册的一些信息。

5.程序测试


加载成功:

附上驱动程序ramblock1:


 1 /* 参考

 2  * driversblockxd.c

 3  * driversblockz2ram.c

 4  */

 5 #include

 6 #include

 7 #include

 8 #include

 9 #include

10 #include

11 #include

12 #include

13 #include

14 #include

15 #include

16 #include

17 #include

18 #include

19 #include

20 #include

21 

22 #include

23 #include

24 #include

25 

26 static struct gendisk *ramblock_disk;     //定义gendisk结构体

27 static struct request_queue *ramblock_queue;     //定义请求队列结构体

28 static DEFINE_SPINLOCK(ramblock_lock);    //定义一个自旋锁

29 static int major;                        //主设备号

30 #define RAMBLOCK_SIZE (1024*1024)        //块设备的容量

31 

32 

33 //file_operation结构体

34 static struct block_device_operations ramblock_fops ={

35     .owner        = THIS_MODULE,

36 };

37 

38 //读写处理函数

39 static void do_ramblock_request(struct request_queue *q)

40 {

41     static int cnt = 0;

42     struct request *req;

43     

44     printk('enter do_ramblock_request %dn',++cnt);

45     

46     req = blk_fetch_request(q);

47     while(req){

48         printk('enter while req %dn',++cnt);

49         break;

50     }

51 

52     __blk_end_request_cur(req, 0);

53     printk('leave do_ramblock_request %dn',++cnt);

54 }

55 

56 static int ramblock_init(void)

57 {

58     printk('ramblock_initn');

59     /* 1.分配一个gendisk结构体 */

60     ramblock_disk = alloc_disk(16); //次设备号个数:分区个数,若为1的话,则意思是只有一个分区

61     

62     /* 2.设置 */

63     /* 2.1 分配/设置队列:函数do_ramblock_request提供读写能力 */

64     ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);

65     

66     /* 2.2 设置其他属性:比如容量 */

67     major = register_blkdev(0,'ramblock');        //cat /proc/device 动态申请一个主设备号

68     

69     ramblock_disk->major = major;                //主设备号

70     ramblock_disk->first_minor = 0;             //第一个次设备号

71     sprintf(ramblock_disk->disk_name, 'ramblock');

72     ramblock_disk->fops = &ramblock_fops;        //操作函数

73     ramblock_disk->queue = ramblock_queue;        //队列

74     set_capacity(ramblock_disk,RAMBLOCK_SIZE/512);    //设置容量,以扇区为单位

75     

76     /* 3.注册 */

77     add_disk(ramblock_disk);    

78     

79     return 0;

80 }

81 

82 static void ramblock_exit(void)

83 {

84     printk('ramblock_exitn');

85     unregister_blkdev(major, 'ramblock');        //卸载主设备号

86     del_gendisk(ramblock_disk);

87     put_disk(ramblock_disk);

88     blk_cleanup_queue(ramblock_queue);

89 }

90 

91 module_init(ramblock_init);

92 module_exit(ramblock_exit);

93 MODULE_LICENSE('GPL');


程序二:增加读写方向,实现挂载等功能


接着前面实现的驱动程序,我们来在它的基础是来实现读写功能以及挂载等功能,


1.分配、释放申请内存


很明显,实现读写的话,那必要要有内存来存储,所以我们必须要入口函数中增加申请内粗的函数。


既然在入口函数中申请了内存,自然就要在出口函数中实现释放内存的操作。

2.在读写函数中实现读写操作。


由于2.6内核的改动,读写函数中的一些对象的名称有点不太一样,不过总体的思路还是一模一样的。参考内核中其他代码的读写函数,


1):实现引入请求队列,并且遍历请求队列


2):当请求队列为真的时候,计算出请求队列的起始地址及长度


3):通过其实地址和长度判读请求是否有效是否超出内存


4):如果以上都通过之后,接下来就是关键了,判断读写方向,接着实现内存的memcpy


5):读写成功后,调用__blk_end_request_cur来返回读写成功与否


3.程序测试

加载驱动:

读写测试:


4.往开发板中增加mkfs命令


接下来就是使用使用mkfs来格式化,但是发现imx257开发板自带的2.6内核里面没有mkfs的命令.


解决办法:使用busybox来创建一个根文件,然后从那个根文件系统中把mkfs命令拷贝到开发板的sbin目录下,就可以了,步骤如下:


1.首先下载busybox-1.23.1.tar.bz2


2.编译busybox


2.1配置busybox


执行命令:make menuconfig ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-


 Busybox Settings --->        //BusyBox的通用配置,一般采用默认值即可。


---Applets

    Archival Utilities --->        //压缩、解压缩相关工具。

    Coreutils --->            //最基本的命令,如cat、cp、ls等。

    Console Utilities --->        //控制台相关命令。

    Debian Utilities --->        //Debian操作系统相关命令。

    Editors --->            //编辑工具,如vi、awk、sed等。

    Finding Utilities --->        //查找工具,如find、grep、xargs。

    Init Utilities --->        //BusyBox init相关命令。

    Login/Password Management Utilities ---> //登陆、用户账号/密码等方面的命令。

    Linux Ext2 FS Progs --->    //ext2文件系统的一些工具。

    Linux Module Utilities --->    //加载/卸载模块等相关的命令。

    Linux System Utilities --->    //一些系统命令。

    Miscellaneous Utilities --->    //一些不好分类的命令,如crond、crontab。

    Networking Utilities --->    //网络相关的命令和工具。

    Print Utilities --->        //print spool服务及相关工具。

    Mail Utilities --->        //mail相关命令。

    Process Utilities --->        //进程相关命令,如ps、kill等。

    Runit Utilities --->        //runit程序。

    Shells --->             //shell程序。

    System Logging Utilities --->    //系统日志相关工具,如syslogd、klogd。


2.2创建文件系统目录


2.2.1.创建文件系统的目录


1 #mkdir /home/study/nfs_home/rootfs_imx257/

2 #cd /nfs_home/rootfs_imx25

3 #mkdir bin dev etc lib sbin proc sys var mnt tmp usr

4 #mkdir usr/bin usr/lib usr/sbin lib/modules

2.2.2.创建设备节点


#cd dev/

#mknod -m 666 console c 5 1 

#mknod -m 666 null c 1 3


2.3配置选项


必须选中和修改的项:

1.'Build Busybox as a static binary(no share libs)'

2.'Don't use /usr'

3.'cross compiler prefix'--------->arm-none-linux-gnueabi-


4.'Busybox Installation prefix'--->/home/study/nfs_home/rootfs_imx257/


****注意此处为你的文件系统目录的路径

(1选择的是静态连接库的方式,如果不选就是使用动态连接库的方式)

(采用动态连接库的方式,在lib目录中添加应用程序所需的库文件)

(Archival Utilities-->gzip这个选项一定不能掉)


找不到的话可以按下/进行搜索.


如图所示:

2.4错误解决


2.4.1错误一


root@Lover雪:/home/study/nfs_home/system/busybox-1.23.1# make CC miscutils/ubi_tools.o

miscutils/ubi_tools.c:67:26: error: mtd/ubi-user.h: No such file or directory

miscutils/ubi_tools.c: In function 'ubi_tools_main':

miscutils/ubi_tools.c:106: error: 'UBI_DEV_NUM_AUTO' undeclared (first use in this function)

miscutils/ubi_tools.c:106: error: (Each undeclared identifier is reported only once

miscutils/ubi_tools.c:106: error: for each function it appears in.)

miscutils/ubi_tools.c:107: error: 'UBI_VOL_NUM_AUTO' undeclared (first use in this function)

miscutils/ubi_tools.c:114: error: field 'attach_req' has incomplete type

miscutils/ubi_tools.c:115: error: field 'mkvol_req' has incomplete type

miscutils/ubi_tools.c:116: error: field 'rsvol_req' has incomplete type

miscutils/ubi_tools.c:177: error: 'UBI_IOCATT' undeclared (first use in this function)

miscutils/ubi_tools.c:190: error: 'UBI_IOCDET' undeclared (first use in this function)

miscutils/ubi_tools.c:233: error: 'UBI_DYNAMIC_VOLUME' undeclared (first use in this function)

miscutils/ubi_tools.c:235: error: 'UBI_STATIC_VOLUME' undeclared (first use in this function)

miscutils/ubi_tools.c:238: error: 'UBI_MAX_VOLUME_NAME' undeclared (first use in this function)

miscutils/ubi_tools.c:243: error: 'UBI_IOCMKVOL' undeclared (first use in this function) 

miscutils/ubi_tools.c:256: error: 'UBI_IOCRMVOL' undeclared (first use in this function) 

miscutils/ubi_tools.c:274: error: 'UBI_IOCRSVOL' undeclared (first use in this function) 

miscutils/ubi_tools.c:290: error: 'UBI_IOCVOLUP' undeclared (first use in this function) 

scripts/Makefile.build:197: recipe for target 'miscutils/ubi_tools.o' failed

make[1]: *** [miscutils/ubi_tools.o] Error 1

Makefile:741: recipe for target 'miscutils' failed

make: *** [miscutils] Error 2

解决方法


拷贝linux内核中的ubi-user.h到busybox下的mtd目录中


mkdir ./include/mtd;cp ../linux-2.6.31/include/mtd/ubi-user.h ./include/mtd/

2.4.2错误二:


networking/udhcp/dhcpc.c: In function 'udhcp_recv_raw_packet':

networking/udhcp/dhcpc.c:852: error: invalid application of 'sizeof' to incomplete type 'struct tpacket_auxdata'

networking/udhcp/dhcpc.c:915: error: 'PACKET_AUXDATA' undeclared (first use in

解决方法:不要编译dhcp模块

e5dfefd8f5f66f016894127ead1a43a4_151448291513652.png

2.5编译安装


配置好之后,运行编译命令:make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-


安装入文件系统:make install

2.6 利用busybox的命令格式化


不必挂载文件系统,只需要利用nfs进入busybox创建的文件系统中,拷贝格式化的mkfs命令到/sbin/下,然后就可以开始格式化了

2.6.1格式化文件系统

f76501e31a125a8a00deafc29d573c59_151448421206657.png3挂载文件系统到/mnt/blk/上

1dc20a1b19fc6f86fcbb4d25b898d06f_151502157296094.png

4读写测试:


建立一个hello.c文件

 

5退出/mnt/blk/目录之后,卸载/mnt/blk/,运行sync是为了同步读写,防止设备忙

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。