一、目的
1.熟悉类 UNIX 系统的 I/O 设备管理
2.熟悉 MINIX 块设备驱动
3.熟悉 MINIX RAM 盘
二、内容与设计思想
测试 RAM 盘和 DISK 盘的文件读写速度,分析其读写速度 差异原因(可用图表形式体 现在实验报告中)。
三、使用环境
Minix,Moba
四、实验过程
1、增加 RAM 盘: 修改/usr/src/minix/drivers/storage/memory/memory.c ,增加默认的用户 RAM 盘数: RAMDISKS=7。重新编译内核,reboot。
2、创建设备 mknod /dev/myram b 1 13,查看设备是否创建成功输入 ls /dev/ | grep ram。 实现 buildmyram 初始化工具(用于分配容量)。
3、参考/usr/src/minix/commands/ramdisk/ramdisk.c,实现 buildmyram.c,但是需要将 KB 单 位修改成 MB。
4、编译 buildmyram.c 文件,然后执行命令: buildmyram /dev/myram。创建一 个 RAM 盘。
5、在 ram 盘上创建内存文件系统,mkfs.mfs /dev/myram。将 ram 盘挂载到用户目录下,mount /dev/myram /root/myram,查看是否 挂在成功:输入 df。
注:重启后用户自定义的ram盘内容会丢失,需要重新设置大小,创建文件系统,并挂载。
6、出现write error错误,应该是因为空间太小了,可以考虑缩小读写次数或者增大磁盘容量,我这里将128MB设置成1GB,这个问题就消失了。
五、总结
刚开始,因为追求块大小的最大值将其设为65536,导致重复的次数减少设为500,最终得出了disk性能优于ram的结论,与假设矛盾。所以之后将块大小调成4096,而增加重复次数为10000,并且删除myram文件夹里的缓存文件,结论恢复正常,但读操作仍然还有改进空间。
六、测试代码
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <sys/wait.h>
/* macro */
#define Concurrency 15 // max concurrent process
//#define repeat 500 // repeat times
#define repeat 10000 // repeat times
//#define Blocksize 65536 // max blocksize
#define Blocksize 4096 // max blocksize
#define maxline (50 * 1024) // array size
#define mod 1000000007 // a big prime number
/* global variables */
long long writetext[maxline]; // testing array
long long readbuff[maxline]; // buff array
struct timeval starttime, endtime, spendtimeSpec; // used to calculate time
char *filepathdisk[19] =
{"/usr/disk1.txt", "/usr/disk2.txt", "/usr/disk3.txt", "/usr/disk4.txt",
"/usr/disk5.txt", "/usr/disk6.txt", "/usr/disk7.txt", "/usr/disk8.txt",
"/usr/disk9.txt", "/usr/disk10.txt", "/usr/disk11.txt", "/usr/disk12.txt",
"/usr/disk13.txt", "/usr/disk14.txt", "/usr/disk15.txt", "/usr/disk16.txt",
"/usr/disk17.txt", "/usr/disk18.txt", "/usr/disk19.txt"};
char *filepathram[19] =
{"/root/myram/ram_test1", "/root/myram/ram_test2", "/root/myram/ram_test3", "/root/myram/ram_test4",
"/root/myram/ram_test5", "/root/myram/ram_test6", "/root/myram/ram_test7", "/root/myram/ram_test8",
"/root/myram/ram_test9", "/root/myram/ram_test10", "/root/myram/ram_test11", "/root/myram/ram_test12",
"/root/myram/ram_test13", "/root/myram/ram_test14", "/root/myram/ram_test15", "/root/myram/ram_test16",
"/root/myram/ram_test17", "/root/myram/ram_test18", "/root/myram/ram_test19"};
/* write files */
void write_file(int blocksize, bool isrand, char *filepath)
{
int fp = open(filepath, O_RDWR | O_CREAT | O_SYNC, 0755);
if (fp > 0)
{
for (int i = 0; i < repeat; i++)
{
int x = write(fp, writetext, blocksize);
if (x < 0)
{
printf("write error!");
break;
}
if (!isrand)
lseek(fp, (repeat-1)*(rand() % blocksize), SEEK_SET);
}
}
else
{
printf("open error!");
}
lseek(fp, 0, SEEK_SET);
}
/* read files */
void read_file(int blocksize, bool isrand, char *filepath)
{
int fp = open(filepath, O_RDONLY);
int i = 0;
if (fp > 0)
{
for (; i < repeat; i++)
{
int x = read(fp, readbuff, blocksize);
if (x < 0)
{
printf("read error!\n");
break;
}
if (!isrand)
lseek(fp, (repeat-1)*(rand() % blocksize), SEEK_SET);
}
}
else
{
printf("open error!");
}
lseek(fp, 0, SEEK_SET);
}
/* get time left */
long get_time_left(struct timeval starttime, struct timeval endtime)
{
long spendtime = 1000000 * (endtime.tv_sec - starttime.tv_sec) + (endtime.tv_usec - starttime.tv_usec); /* us */
return spendtime;
}
void test1()
{
printf("Ram Sequential Write\n");
printf("block\tprocess\tlatency\n");
double BLOCK=0;
double LATENCY=0;
for (int block = 64; block <= Blocksize; block *= 2)
{
for (int concurrency = 1; concurrency <= Concurrency; concurrency ++)
{
gettimeofday(&starttime, NULL);
for (int i = 0; i < concurrency; i++)
{
if (fork() == 0)
{
write_file(block, true, filepathram[i]); //ram sequential write
exit(1);
}
}
// wait children to terminate
while (wait(NULL) != -1)
;
gettimeofday(&endtime, NULL);
/* calculate the duration, latency, file_MB */
long alltime = get_time_left(starttime, endtime); // get the duration (us)
double latency = (alltime) / (double)repeat / (double)concurrency; // single file latency (us)
double file_MB = (double)block * repeat * concurrency / 1024.0 / 1024.0; // filesize in total
BLOCK+=block;
LATENCY+=latency;
printf("%d\t%d\t%.2f\n", block, concurrency, latency);
}
double throughput=BLOCK/LATENCY;
printf("%.3f\n",throughput);
BLOCK=LATENCY=0;
}
}
void test2()
{
printf("Ram Random Write\n");
printf("block\tprocess\tlatency\n");
double BLOCK=0;
double LATENCY=0;
for (int block = 64; block <= Blocksize; block *= 2)
{
for (int concurrency = 1; concurrency <= Concurrency; concurrency ++)
{
gettimeofday(&starttime, NULL);
for (int i = 0; i < concurrency; i++)
{
if (fork() == 0)
{
write_file(block, false, filepathram[i]); //ram random write
exit(1);
}
}
// wait children to terminate
while (wait(NULL) != -1)
;
gettimeofday(&endtime, NULL);
/* calculate the duration, latency, file_MB */
long alltime = get_time_left(starttime, endtime); // get the duration (us)
double latency = (alltime) / (double)repeat / (double)concurrency; // single file latency (us)
double file_MB = (double)block * repeat * concurrency / 1024.0 / 1024.0; // filesize in total
BLOCK+=block;
LATENCY+=latency;
printf("%d\t%d\t%.2f\n", block, concurrency, latency);
}
double throughput=BLOCK/LATENCY;
printf("%.3f\n",throughput);
BLOCK=LATENCY=0;
}
}
void test3()
{
printf("Ram Sequential Read\n");
printf("block\tprocess\tlatency\n");
double BLOCK=0;
double LATENCY=0;
for (int block = 64; block <= Blocksize; block *= 2)
{
for (int concurrency = 1; concurrency <= Concurrency; concurrency ++)
{
gettimeofday(&starttime, NULL);
for (int i = 0; i < concurrency; i++)
{
if (fork() == 0)
{
read_file(block, true, filepathram[i]); //ram sequential read
exit(1);
}
}
// wait children to terminate
while (wait(NULL) != -1)
;
gettimeofday(&endtime, NULL);
/* calculate the duration, latency, file_MB*/
long alltime = get_time_left(starttime, endtime); // get the duration (us)
double latency = (alltime) / (double)repeat / (double)concurrency; // single file latency (us)
double file_MB = (double)block * repeat * concurrency / 1024.0 / 1024.0; // filesize in total
BLOCK+=block;
LATENCY+=latency;
printf("%d\t%d\t%.2f\n", block, concurrency, latency);
}
double throughput=BLOCK/LATENCY;
printf("%.3f\n",throughput);
BLOCK=LATENCY=0;
}
}
void test4()
{
printf("Ram Random Read\n");
printf("block\tprocess\tlatency\n");
double BLOCK=0;
double LATENCY=0;
for (int block = 64; block <= Blocksize; block *= 2)
{
for (int concurrency = 1; concurrency <= Concurrency; concurrency ++)
{
gettimeofday(&starttime, NULL);
for (int i = 0; i < concurrency; i++)
{
if (fork() == 0)
{
read_file(block, false, filepathram[i]); //ram random read
exit(1);
}
}
// wait children to terminate
while (wait(NULL) != -1)
;
gettimeofday(&endtime, NULL);
/* calculate the duration, latency, file_MB*/
long alltime = get_time_left(starttime, endtime); // get the duration (us)
double latency = (alltime) / (double)repeat / (double)concurrency; // single file latency (us)
double file_MB = (double)block * repeat * concurrency / 1024.0 / 1024.0; // filesize in total
BLOCK+=block;
LATENCY+=latency;
printf("%d\t%d\t%.2f\n", block, concurrency, latency);
}
double throughput=BLOCK/LATENCY;
printf("%.3f\n",throughput);
BLOCK=LATENCY=0;
}
}
void test5()
{
printf("Disk Sequential Write\n");
printf("block\tprocess\tlatency\n");
double BLOCK=0;
double LATENCY=0;
for (int block = 64; block <= Blocksize; block *= 2)
{
for (int concurrency = 1; concurrency <= Concurrency; concurrency ++)
{
gettimeofday(&starttime, NULL);
for (int i = 0; i < concurrency; i++)
{
if (fork() == 0)
{
write_file(block, true, filepathdisk[i]); //disk sequential write
exit(1);
}
}
// wait children to terminate
while (wait(NULL) != -1)
;
gettimeofday(&endtime, NULL);
/* calculate the duration, latency, file_MB */
long alltime = get_time_left(starttime, endtime); // get the duration (us)
double latency = (alltime) / (double)repeat / (double)concurrency; // single file latency (us)
double file_MB = (double)block * repeat * concurrency / 1024.0 / 1024.0; // filesize in total
BLOCK+=block;
LATENCY+=latency;
printf("%d\t%d\t%.2f\n", block, concurrency, latency);
}
double throughput=BLOCK/LATENCY;
printf("%.3f\n",throughput);
BLOCK=LATENCY=0;
}
}
void test6()
{
printf("Disk Random Write\n");
printf("block\tprocess\tlatency\n");
double BLOCK=0;
double LATENCY=0;
for (int block = 64; block <= Blocksize; block *= 2)
{
for (int concurrency = 1; concurrency <= Concurrency; concurrency ++)
{
gettimeofday(&starttime, NULL);
for (int i = 0; i < concurrency; i++)
{
if (fork() == 0)
{
write_file(block, false, filepathdisk[i]); //disk random write
exit(1);
}
}
// wait children to terminate
while (wait(NULL) != -1)
;
gettimeofday(&endtime, NULL);
/* calculate the duration, latency, file_MB */
long alltime = get_time_left(starttime, endtime); // get the duration (us)
double latency = (alltime) / (double)repeat / (double)concurrency; // single file latency (us)
double file_MB = (double)block * repeat * concurrency / 1024.0 / 1024.0; // filesize in total
BLOCK+=block;
LATENCY+=latency;
printf("%d\t%d\t%.2f\n", block, concurrency, latency);
}
double throughput=BLOCK/LATENCY;
printf("%.3f\n",throughput);
BLOCK=LATENCY=0;
}
}
void test7()
{
printf("Disk Sequential Read\n");
printf("block\tprocess\tlatency\n");
double BLOCK=0;
double LATENCY=0;
for (int block = 64; block <= Blocksize; block *= 2)
{
for (int concurrency = 1; concurrency <= Concurrency; concurrency ++)
{
gettimeofday(&starttime, NULL);
for (int i = 0; i < concurrency; i++)
{
if (fork() == 0)
{
read_file(block, true, filepathdisk[i]); //disk sequential read
exit(1);
}
}
// wait children to terminate
while (wait(NULL) != -1)
;
gettimeofday(&endtime, NULL);
/* calculate the duration, latency, file_MB */
long alltime = get_time_left(starttime, endtime); // get the duration (us)
double latency = (alltime) / (double)repeat / (double)concurrency; // single file latency (us)
double file_MB = (double)block * repeat * concurrency / 1024.0 / 1024.0; // filesize in total
BLOCK+=block;
LATENCY+=latency;
printf("%d\t%d\t%.2f\n", block, concurrency, latency);
}
double throughput=BLOCK/LATENCY;
printf("%.3f\n",throughput);
BLOCK=LATENCY=0;
}
}
void test8()
{
printf("Disk Random Read\n");
printf("block\tprocess\tlatency\n");
double BLOCK=0;
double LATENCY=0;
for (int block = 64; block <= Blocksize; block *= 2)
{
for (int concurrency = 1; concurrency <= Concurrency; concurrency ++)
{
gettimeofday(&starttime, NULL);
for (int i = 0; i < concurrency; i++)
{
if (fork() == 0)
{
read_file(block, false, filepathdisk[i]); //disk random read
exit(1);
}
}
// wait children to terminate
while (wait(NULL) != -1)
;
gettimeofday(&endtime, NULL);
/* calculate the duration, latency, file_MB */
long alltime = get_time_left(starttime, endtime); // get the duration (us)
double latency = (alltime) / (double)repeat / (double)concurrency; // single file latency (us)
double file_MB = (double)block * repeat * concurrency / 1024.0 / 1024.0; // filesize in total
BLOCK+=block;
LATENCY+=latency;
printf("%d\t%d\t%.2f\n", block, concurrency, latency);
}
double throughput=BLOCK/LATENCY;
printf("%.3f\n",throughput);
BLOCK=LATENCY=0;
}
}
int main()
{
srand((unsigned)time(NULL));
int i = 0;
// initial a test array
for (int j = 0; j < maxline; j++)
writetext[j] = (j * j * j - 3 * Blocksize * j) % mod;
test1();
printf("\n");
test2();
printf("\n");
test3();
printf("\n");
test4();
printf("\n");
test5();
printf("\n");
test6();
printf("\n");
test7();
printf("\n");
test8();
printf("\n");
return 0;
}