读写文件
来源:互联网 发布:网络编辑是什么来的 编辑:程序博客网 时间:2024/06/06 14:35
添加用户接口,添加声明略:
kernel/fs.c
- /*--------------------------------------------------------------------Write_File
- 用户接口
- 把buf缓冲区的前write_bytes个字节写到fd指定的文件中
- 如果失败返回-1
- */
- int Write_File(int fd,const void *buf,u32 write_bytes)
- {
- Message m;
- m.msg_type = FS_WRITE_FILE;
- m.i1 = fd;
- m.i2 = write_bytes;
- m.p1 = buf;
- Send_Receive_Shell(BOTH,PROC_FS_PID,&m);
- return m.r1;
- }
- /*---------------------------------------------------------------------Read_File
- 用户接口
- 从fd指定的文件中从当前的pos处读read_bytes个字节到buf缓冲区
- 如果失败返回-1
- */
- int Read_File(int fd,const void *buf,u32 read_bytes)
- {
- Message m;
- m.msg_type = FS_READ_FILE;
- m.i1 = fd;
- m.i2 = read_bytes;
- m.p1 = buf;
- Send_Receive_Shell(BOTH,PROC_FS_PID,&m);
- return m.r1;
- }
在FS进程中处理这两种消息,在执行体中追加:
kernel/fs.c
- /* 读写文件消息,交给Do_Read_Write_File函数处理 */
- case FS_READ_FILE:
- case FS_WRITE_FILE:
- m.r1 = Do_Read_Write_File(&m);
- break;
我们看到,读写都交给了同一个函数处理,因为读和写有很多相似的地方:
- /*------------------------------------------------------------Do_Read_Write_File
- 读写文件处理函数
- 失败则返回-1
- */
- static int Do_Read_Write_File(Message *m)
- {
- int fd = m->i1; /* 取出fd */
- u32 rdwr_bytes_size = m->i2; /* 取出读写的字节数 */
- u8 *rdwr_buf = m->p1; /* 取出读写缓冲区指针 */
- u8 *fs_buf = (u8*)FS_BUF; /* 取得读写扇区缓冲区指针 */
- PCB *p_caller = &PCB_Table[m->src_proc_pid]; /* 取得调用者进程的PCB指针 */
- /* 如果创建文件时的flag的读写位不为1,则返回-1 */
- if(!(p_caller->fd_ptr_table[fd]->fd_access_mode & O_RDWR))
- {
- Printf("Could Read & Write!/n");
- return -1;
- }
- I_Node *p_inode = p_caller->fd_ptr_table[fd]->fd_inode; /* 取得i结点 */
- u32 pos = p_caller->fd_ptr_table[fd]->fd_pos; /* 取得读写位置 */
- /* 如果是写文件,则判断是否超过文件实际占用空间 */
- if(m->msg_type == FS_WRITE_FILE)
- {
- if(pos + rdwr_bytes_size > p_inode->i_sect_total * SECTOR_SIZE)
- {
- Printf("Write Error,Beyond the Limit!/n");
- return -1;
- }
- }
- /* 如果是读文件,则判断是否超过文件实际大小 */
- else if(m->msg_type == FS_READ_FILE)
- {
- if(pos + rdwr_bytes_size > p_inode->i_size)
- {
- Printf("Read Error,Beyond the Limit!/n");
- return -1;
- }
- }
- u32 end_pos = pos + rdwr_bytes_size; /* 取得读写的末位置 */
- u32 begin_sec = p_inode->i_start_sec + pos / SECTOR_SIZE; /* 求得起始扇区 */
- u32 end_sec = p_inode->i_start_sec + end_pos / SECTOR_SIZE; /* 求得结束扇区 */
- u32 left_bytes = rdwr_bytes_size; /* 读写的剩余字节 */
- u32 done_bytes = 0; /* 读写完成的字节数,待返回 */
- u32 copy_bytes = 0; /* 当前应copy的字节数 */
- /* 遍历涉及到的扇区 */
- int i;
- for(i = 0;i < end_sec - begin_sec + 1;i++)
- {
- /* 如果读写工作在当前扇区完成不了,则。。看代码 */
- if((pos % SECTOR_SIZE) + left_bytes > SECTOR_SIZE)
- {
- copy_bytes = SECTOR_SIZE - (pos % SECTOR_SIZE);
- }
- /* 反之 */
- else
- {
- copy_bytes = left_bytes;
- }
- /* 读入当前扇区 */
- Read_Sector(p_inode->i_dev,begin_sec + i);
- /* 写 */
- if(m->msg_type == FS_WRITE_FILE)
- {
- Memory_Copy(fs_buf + (pos % SECTOR_SIZE),rdwr_buf,copy_bytes);
- }
- /* 读 */
- else if(m->msg_type == FS_READ_FILE)
- {
- Memory_Copy(rdwr_buf,fs_buf + (pos % SECTOR_SIZE),copy_bytes);
- }
- pos += copy_bytes; /* 移动pos到下一个读写位置 */
- /* 更新工作 */
- left_bytes -= copy_bytes;
- done_bytes += copy_bytes;
- Write_Sector(p_inode->i_dev,begin_sec + i); /* 写回 */
- }
- /* 写 */
- if(m->msg_type == FS_WRITE_FILE)
- {
- p_caller->fd_ptr_table[fd]->fd_pos = pos; /* 读写位置写回fd */
- /* 如果写位置超过了当前文件大小,则更新文件的大小 */
- if(pos > p_inode->i_size)
- {
- p_inode->i_size = pos;
- }
- Syn_I_Node(p_inode); /* 写回此文件的i结点 */
- }
- return done_bytes; /* 返回读写的自己数 */
- }
用到的宏如下:
include/const.h
- #define FS_READ_FILE 8 /* 读文件 */
- #define FS_WRITE_FILE 9 /* 写文件 */
OK,那么在进程A中来测试,首先创建一个名为first_file的文件,向其中写入my first file这个串,关闭该文件,再次打开,读取前8个字节并打印出来。是不是跟前面用Linux写的代码有点点像。代码如下:
kernel/proc.c
- /*------------------------------------------------------------------------Proc_A
- 进程A的执行体
- */
- void Proc_A()
- {
- char write_buf[] = "my first file";
- const int read_bytes = 8;
- char read_buf[read_bytes];
- int fd = -1;
- fd = Open("/first_file",O_CREATE | O_RDWR);
- Assert(fd != -1);
- Printf("FD:%d/n",fd);
- Assert(Write_File(fd,write_buf,Str_Len(write_buf)) != -1);
- Close(fd);
- fd = -1;
- fd = Open("/first_file",O_RDWR);
- Assert(fd != -1);
- Printf("FD:%d/n",fd);
- Assert(Read_File(fd,read_buf,read_bytes) != -1);
- read_buf[read_bytes] = '/0';
- Printf("Read File:%s/n",read_buf);
- while(1)
- {
- //Milli_Delay(200);
- //Printf("%d ",Get_Ticks());
- Milli_Delay(200);
- }
- }
OK,make,bochs,运行结果如下:
嗯,这样看是成功了,还得看看硬盘里的数据,先看看这个文件在硬盘的哪个地方,通过查看该文件的i结点数组得到相对当前分区的扇区偏移为0x18e,这样得到相对整个硬盘的偏移字节数为:0x9dfe00+0x18e*512=0xa11a00,查看这个地儿:
嗯,看到数据了,虽然没有很全面的测试,但起码这里没错,等到有人给我抓到BUG的时候再改吧。。