I/O subsystem
目标
熟悉类UNIX系统的I/O设备管理
熟悉MINIX块设备驱动
熟悉MINIX RAM盘
实验要求
在MINIX3中安装一块X MB大小的RAM盘(minix中已有6块用户可用RAM盘,7块系统保留RAM盘),可以挂载并且存取文件操作。
测试RAM盘和DISK盘的文件读写速度,分析其读写速度差异原因(可用图表形式体现在实验报告中)。
实现过程
增加RAM盘:
- 修改
/usr/src/minix/drivers/storage/memory/memory.c
,增加默认的用户RAM盘数:RAMDISKS=7
。
- 重新编译内核,重启reboot。
- 创建设备
mknod /dev/myram b 1 13
,查看设备是否创建成功输入ls /dev/ | grep ram
。
实现
buildmyram
初始化工具(用于分配容量)。- 参考
/usr/src/minix/commands/ramdisk/ramdisk.c
,实现buildmyram.c
,但是需要将KB单位修改成MB。 ramdisk.c
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
int
main(int argc, char *argv[])
{
int fd;
signed long size;
char *d;
if(argc < 2 || argc > 3) {
fprintf(stderr, "usage: %s <size in kB> [device]\n",
argv[0]);
return 1;
}
d = argc == 2 ? _PATH_RAMDISK : argv[2];
if((fd=open(d, O_RDONLY)) < 0) {
perror(d);
return 1;
}
size = atol(argv[1])*KFACTOR;
if(size < 0) {
fprintf(stderr, "size should be non-negative.\n");
return 1;
}
if(ioctl(fd, MIOCRAMSIZE, &size) < 0) {
perror("MIOCRAMSIZE");
return 1;
}
fprintf(stderr, "size on %s set to %ldkB\n", d, size/KFACTOR);
return 0;
}- 编译
buildmyram.c
文件,然后执行命令:./buildmyram <size in MB> /dev/myram
。创建一个RAM盘。
- 参考
我们将KB变成MB ,可以这样写:
1 |
|
在ram盘上创建内存文件系统,
mkfs.mfs /dev/myram
。将ram盘挂载到用户目录下,
mount /dev/myram /root/myram
,(首先必须先mkdir myram
)查看是否挂在成功:输入df,结果如下:
其中,GB、MB、512-block 转换方式如下:
GB | MB | 512-blocks |
---|---|---|
1 | 1024 | 2097152 |
- 注:重启后用户自定义的ram盘内容会丢失,需要重新设置大小,创建文件系统,并挂载。
重启后,我们会发现刚刚创建的ram盘就丢失了,我们就需要重复下面三条命令:
1 | ./buildmyram 700 /dev/myram // 因为吞吐量不会大于700MB/s 这里就把Ram盘设置为700mb |
性能测试:
RAM盘和Disk盘的性能测试中,需要采用多进程并发的同步读写,并发数要增加到设备接近“饱和”状态(吞吐量难以继续提升,但是I/O延时恶化)。在出现饱和前,总吞吐量随着并发数线性增长。
性能测试的二个变量为块大小(推荐64B/256B/1KB/4KB/16KB/64KB)和块扫描方式(顺序/随机)。可以画四张曲线图对比RAM盘和Disk盘性能(随机读,随机写,顺序读,顺序写)。实验结果预计为RAM盘性能高于DISK盘,特别是随机读写性能。对比在不同的blocksize下的性能,然后通过Excel把数据制作成图表。
编写测试文件
注意事项
- 使用posix函数open打开文件,利用O_SYNC参数使得write/read操作为同步模式。
- 一定要检查write/read函数的返回值,以及写入的字节数目,确定是否成功。
- 为了简化实验,可以为每个进程分配一个独立的文件。为了减小主机操作系统的缓存机制造成的误差,文件总大小越大越好(例如300MB)。
- 随机读写时,可以采用
lseek()
重新定位文件指针;顺序读写时,默认文件指针自动移动,当读到文件末尾时,可以用lseek()
返回文件头。 - 每组的读写需要反复持续一段时间,过短的时间会造成误差较大。
- 通常情况下,7~15个进程达到饱和,吞吐量不会高于700MB/s (ram盘顺序读写)。
- 如果minix虚拟机建在SSD下,会导致随机和顺序的差距减小,所以最好把虚拟机放在机械硬盘上,实验效果更明显。
首先, usr文件夹是硬盘, 而myram 文件夹是内存。我们需要将一个尽可能大的文件放到这两个文件夹中去。
写方法
写文件:打开文件,判断返回值,如果正常打开文件就判断是否随机写,进行写操作
这里要说一下打开文件的方式,O_CREAT,O_RDWR,O_SYNC
以及权限编码:
O_RDWR
即以可读写的方式打开文件
O_SYNC
以同步的方式打开文件,利用O_SYNC
参数使得write/read
操作为同步模式
O_CREAT
若想要打开的文件不存在则自动建立该文件
后面四位数字分别代表 全部用户(all), 文件用户(user),同组用户(group),其他用户(other) 的权限
十进制 | 二进制 | 代表 |
---|---|---|
0 | 000 | 无 |
1 | 001 | —x(只可执行) |
2 | 010 | -w-(只可写) |
3 | 011 | -wx(可写可执行) |
4 | 100 | r—(只可读) |
5 | 101 | r-x(可读可执行) |
6 | 110 | rw-(可读可写) |
7 | 111 | rwx(可读可写可执行) |
1 | // 向缓存中写入大小为blocksize的数字 |
读方法
读方法和写方法的结构是一样的
1 |
|
主函数
主函数:首先创建和命名文件,通过循环执行read_file
和write_file
函数测试读写差异。测试blocksize
和concurrency
对测试读写速度的影响,最后输出结果。
1 | //首先写两个 utils, 第一个函数是获取当前的时间 |
1 |
|
数据如下:
分块大小 | ram | disk |
---|---|---|
64 | 12.387097 | 10.858385 |
256 | 47.872838 | 27.863946 |
1024 | 157.538462 | 91.237491 |
4096 | 380.19802 | 180.705582 |
16384 | 550.044763 | 236.307692 |
66536 | 646.736842 | 257.826269 |
分块大小 | ram | disk |
64 | 17.886463 | 8.031373 |
256 | 71.300917 | 47.690775 |
1024 | 228.997391 | 110.048361 |
4096 | 519.357566 | 169.185606 |
16384 | 722.823529 | 195.047619 |
66536 | 783.673469 | 201.442623 |
分块大小 | ram | disk |
64 | 4.561823 | 5.918561 |
256 | 20.2999336 | 11.837121 |
1024 | 71.168771 | 23.674242 |
4096 | 297.24238 | 47.348485 |
16384 | 550.537634 | 94.69697 |
66536 | 695.022624 | 189.393939 |
分块大小 | ram | disk |
64 | 5.809929 | 0.610483 |
256 | 24.924949 | 2.032418 |
1024 | 96 | 8.908608 |
4096 | 372.353636 | 55.941 |
16384 | 625.025432 | 139.098936 |
66536 | 722.823529 | 219.428571 |
结果如下图所示:
将随机