冬天OS(二十九):文件系统读写接口

--------------------------------------------------------

文件系统读写接口

--------------------------------------------------------

这节我们接着为文件系统添加读写接口!

 

·TestA 函数
void TestA()
{
	int fd;
	int n;
	const char filename[] = "blah";
	const char bufw[] = "Hello World!!";
	
	const int rd_bytes = strlen(bufw);
	char bufr[rd_bytes + 1];

	assert(rd_bytes <= strlen(bufw));

	/* create */
	fd = open(filename, O_CREAT | O_RDWR);
	assert(fd != -1);
	printf("File created. fd: %d\n", fd);

	/* write */
	n = write(fd, bufw, strlen(bufw));
	assert(n == strlen(bufw));

	/* close */
	close(fd);

	/* open */
	fd = open(filename, O_RDWR);
	assert(fd != -1);
	printf("File opened. fd: %d\n", fd);

	/* read */
	n = read(fd, bufr, rd_bytes);
	assert(n == rd_bytes);
	bufr[n + 1] = 0;
	printf("%d bytes read: %s\n", n, bufr);

	/* close */
	close(fd);

	spin("TestA");
}

 

·do_rdwt 函数
PUBLIC int do_rdwt()
{
	int fd = fs_msg.FD;		 /* 文件描述符 */
	void *buf = fs_msg.BUF;  /* 读写缓冲区 */
	int len = fs_msg.CNT;	/* 长度 */
	int src = fs_msg.source; /* caller proc nr. */
	assert((pcaller->filp[fd] >= &f_desc_table[0]) &&
		   (pcaller->filp[fd] < &f_desc_table[NR_FILE_DESC]));

	// 检测文件描述符标志
	if (!(pcaller->filp[fd]->fd_mode & O_RDWR))
		return -1;

	int pos = pcaller->filp[fd]->fd_pos;
	struct inode *pin = pcaller->filp[fd]->fd_inode;
	assert(pin >= &inode_table[0] && pin < &inode_table[NR_INODE]);

	int imode = pin->i_mode & I_TYPE_MASK;
	if (imode == I_CHAR_SPECIAL)
	{
		int t = fs_msg.type == READ ? DEV_READ : DEV_WRITE;
		fs_msg.type = t;

		int dev = pin->i_start_sect;
		assert(MAJOR(dev) == 4);

		fs_msg.DEVICE = MINOR(dev);
		fs_msg.BUF = buf;
		fs_msg.CNT = len;
		fs_msg.PROC_NR = src;
		assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);
		send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &fs_msg);
		assert(fs_msg.CNT == len);

		return fs_msg.CNT;
	}
	else
	{
		assert(pin->i_mode == I_REGULAR || pin->i_mode == I_DIRECTORY);
		assert((fs_msg.type == READ) || (fs_msg.type == WRITE));

		// 预防读写情况下的 pos_end
		int pos_end;
		if (fs_msg.type == READ)									 /* READ */
			pos_end = min(pos + len, pin->i_size);					 /* 这句话的意思是读的时候只能读到 i_size  */
		else														 /* WRITE */
			pos_end = min(pos + len, pin->i_nr_sects * SECTOR_SIZE); /* 这句话的意思是写的时候可以写到 2048 sectors */

		// 根据长度计算需要读取多少扇区从磁盘中
		int off = pos % SECTOR_SIZE;
		int rw_sect_min = pin->i_start_sect + (pos >> SECTOR_SIZE_SHIFT);	 /* 从哪个扇区开始读 */
		int rw_sect_max = pin->i_start_sect + (pos_end >> SECTOR_SIZE_SHIFT); /* 可以读止哪个扇区 */
		int chunk = min(rw_sect_max - rw_sect_min + 1,						  /* 一共要读多少块 */
						FSBUF_SIZE >> SECTOR_SIZE_SHIFT);					  /*  FSBUF_SIZE >> SECTOR_SIZE_SHIFT == 2048 */

		int bytes_rw = 0;
		int bytes_left = len;
		int i;
		for (i = rw_sect_min; i <= rw_sect_max; i += chunk) /* 循环无用 */
		{
			/* read/write this amount of bytes every time */
			int bytes = min(bytes_left, chunk * SECTOR_SIZE - off);
			rw_sector(DEV_READ,
					  pin->i_dev,
					  i * SECTOR_SIZE,	 /* 起始扇区 */
					  chunk * SECTOR_SIZE, /* 这不就是一次将要读的扇区都读出来吗 */
					  TASK_FS,
					  fsbuf);

			if (fs_msg.type == READ) /* 将要求长度的数据赋值到用户缓冲区中 */
			{
				phys_copy((void *)va2la(src, buf + bytes_rw),
						  (void *)va2la(TASK_FS, fsbuf + off), /* 注意这里的 fsbuf + off 关键 */
						  bytes);							   /* 但是 对 fsbuf va2la 没有必要 */
			}
			else /* 将要求长度的数据写到 buf 缓冲区中并刷新到磁盘中 */
			{
				phys_copy((void *)va2la(TASK_FS, fsbuf + off),
						  (void *)va2la(src, buf + bytes_rw),
						  bytes);

				// 刷新到磁盘中
				rw_sector(DEV_WRITE,
						  pin->i_dev,
						  i * SECTOR_SIZE,
						  chunk * SECTOR_SIZE,
						  TASK_FS,
						  fsbuf);
			}
			off = 0;
			bytes_rw += bytes;					/* 记录已经写了 / 读了多少字节 */
			pcaller->filp[fd]->fd_pos += bytes; /* 更新文件描述符的 pos(注意不是 inode 的 size) */
			bytes_left -= bytes;
		}

		if (pcaller->filp[fd]->fd_pos > pin->i_size) /* 写到了超过 inode 本来的 size */
		{											 /* 就要更新 i_size ,其余情况不需要更新 i_size */
			pin->i_size = pcaller->filp[fd]->fd_pos;
			sync_inode(pin);
		}

		return bytes_rw;
	}
}

——其中的循环没有存在的必要,到时候可以去掉!
 

运行

 

可以看到,确实读出了我们写进磁盘的字符串,每次打开文件 pos 都是在起始位置的! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sssnial-jz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值