读写文件

来源:互联网 发布:网络编辑是什么来的 编辑:程序博客网 时间:2024/06/06 14:35

    添加用户接口,添加声明略:

    kernel/fs.c

Code:
  1. /*--------------------------------------------------------------------Write_File  
  2.     用户接口  
  3.     把buf缓冲区的前write_bytes个字节写到fd指定的文件中  
  4.     如果失败返回-1  
  5. */  
  6.   
  7. int Write_File(int fd,const void *buf,u32 write_bytes)   
  8. {   
  9.     Message m;   
  10.     m.msg_type = FS_WRITE_FILE;   
  11.     m.i1 = fd;   
  12.     m.i2 = write_bytes;   
  13.     m.p1 = buf;   
  14.        
  15.     Send_Receive_Shell(BOTH,PROC_FS_PID,&m);   
  16.     return m.r1;   
  17. }   
  18.   
  19. /*---------------------------------------------------------------------Read_File  
  20.     用户接口  
  21.     从fd指定的文件中从当前的pos处读read_bytes个字节到buf缓冲区  
  22.     如果失败返回-1  
  23. */  
  24. int Read_File(int fd,const void *buf,u32 read_bytes)   
  25. {   
  26.     Message m;   
  27.     m.msg_type = FS_READ_FILE;   
  28.     m.i1 = fd;   
  29.     m.i2 = read_bytes;   
  30.     m.p1 = buf;   
  31.        
  32.     Send_Receive_Shell(BOTH,PROC_FS_PID,&m);   
  33.     return m.r1;   
  34. }  

    在FS进程中处理这两种消息,在执行体中追加:

    kernel/fs.c

Code:
  1. /* 读写文件消息,交给Do_Read_Write_File函数处理 */  
  2. case FS_READ_FILE:   
  3. case FS_WRITE_FILE:   
  4.     m.r1 = Do_Read_Write_File(&m);   
  5.     break;  

    我们看到,读写都交给了同一个函数处理,因为读和写有很多相似的地方:

Code:
  1. /*------------------------------------------------------------Do_Read_Write_File  
  2.     读写文件处理函数  
  3.     失败则返回-1  
  4. */  
  5. static int Do_Read_Write_File(Message *m)   
  6. {   
  7.     int fd = m->i1;                 /* 取出fd */  
  8.     u32 rdwr_bytes_size = m->i2;    /* 取出读写的字节数 */  
  9.     u8 *rdwr_buf = m->p1;           /* 取出读写缓冲区指针 */  
  10.     u8 *fs_buf = (u8*)FS_BUF;       /* 取得读写扇区缓冲区指针 */  
  11.        
  12.     PCB *p_caller = &PCB_Table[m->src_proc_pid];    /* 取得调用者进程的PCB指针 */  
  13.        
  14.     /* 如果创建文件时的flag的读写位不为1,则返回-1 */  
  15.     if(!(p_caller->fd_ptr_table[fd]->fd_access_mode & O_RDWR))   
  16.     {   
  17.         Printf("Could Read & Write!/n");   
  18.         return -1;   
  19.     }   
  20.        
  21.     I_Node *p_inode = p_caller->fd_ptr_table[fd]->fd_inode; /* 取得i结点 */  
  22.     u32 pos = p_caller->fd_ptr_table[fd]->fd_pos;   /* 取得读写位置 */  
  23.        
  24.     /* 如果是写文件,则判断是否超过文件实际占用空间 */  
  25.     if(m->msg_type == FS_WRITE_FILE)   
  26.     {   
  27.         if(pos + rdwr_bytes_size > p_inode->i_sect_total * SECTOR_SIZE)   
  28.         {   
  29.             Printf("Write Error,Beyond the Limit!/n");   
  30.             return -1;   
  31.         }   
  32.     }   
  33.     /* 如果是读文件,则判断是否超过文件实际大小 */  
  34.     else if(m->msg_type == FS_READ_FILE)   
  35.     {      
  36.         if(pos + rdwr_bytes_size > p_inode->i_size)   
  37.         {   
  38.             Printf("Read Error,Beyond the Limit!/n");   
  39.             return -1;   
  40.         }   
  41.     }   
  42.        
  43.     u32 end_pos = pos + rdwr_bytes_size;    /* 取得读写的末位置 */  
  44.     u32 begin_sec = p_inode->i_start_sec + pos / SECTOR_SIZE;   /* 求得起始扇区 */  
  45.     u32 end_sec = p_inode->i_start_sec + end_pos / SECTOR_SIZE; /* 求得结束扇区 */  
  46.     u32 left_bytes = rdwr_bytes_size;   /* 读写的剩余字节 */  
  47.     u32 done_bytes = 0;     /* 读写完成的字节数,待返回 */  
  48.     u32 copy_bytes = 0;     /* 当前应copy的字节数 */  
  49.        
  50.     /* 遍历涉及到的扇区 */  
  51.     int i;   
  52.     for(i = 0;i < end_sec - begin_sec + 1;i++)   
  53.     {   
  54.         /* 如果读写工作在当前扇区完成不了,则。。看代码 */  
  55.         if((pos % SECTOR_SIZE) + left_bytes > SECTOR_SIZE)   
  56.         {   
  57.             copy_bytes = SECTOR_SIZE - (pos % SECTOR_SIZE);   
  58.         }   
  59.         /* 反之 */  
  60.         else  
  61.         {   
  62.             copy_bytes = left_bytes;   
  63.         }   
  64.         /* 读入当前扇区 */  
  65.         Read_Sector(p_inode->i_dev,begin_sec + i);   
  66.         /* 写 */  
  67.         if(m->msg_type == FS_WRITE_FILE)   
  68.         {   
  69.             Memory_Copy(fs_buf + (pos % SECTOR_SIZE),rdwr_buf,copy_bytes);   
  70.         }   
  71.         /* 读 */  
  72.         else if(m->msg_type == FS_READ_FILE)   
  73.         {   
  74.             Memory_Copy(rdwr_buf,fs_buf + (pos % SECTOR_SIZE),copy_bytes);   
  75.         }   
  76.         pos += copy_bytes;  /* 移动pos到下一个读写位置 */  
  77.         /* 更新工作 */  
  78.         left_bytes -= copy_bytes;   
  79.         done_bytes += copy_bytes;   
  80.         Write_Sector(p_inode->i_dev,begin_sec + i);     /* 写回 */  
  81.     }   
  82.        
  83.     /* 写 */  
  84.     if(m->msg_type == FS_WRITE_FILE)   
  85.     {   
  86.         p_caller->fd_ptr_table[fd]->fd_pos = pos;   /* 读写位置写回fd */  
  87.         /* 如果写位置超过了当前文件大小,则更新文件的大小 */  
  88.         if(pos > p_inode->i_size)   
  89.         {   
  90.             p_inode->i_size = pos;   
  91.         }   
  92.         Syn_I_Node(p_inode);    /* 写回此文件的i结点 */  
  93.     }   
  94.     return done_bytes;  /* 返回读写的自己数 */  
  95. }  

    用到的宏如下:

    include/const.h

Code:
  1. #define FS_READ_FILE                8           /* 读文件 */   
  2. #define FS_WRITE_FILE               9           /* 写文件 */  

    OK,那么在进程A中来测试,首先创建一个名为first_file的文件,向其中写入my first file这个串,关闭该文件,再次打开,读取前8个字节并打印出来。是不是跟前面用Linux写的代码有点点像。代码如下:

    kernel/proc.c

Code:
  1. /*------------------------------------------------------------------------Proc_A  
  2.     进程A的执行体   
  3. */  
  4. void Proc_A()   
  5. {      
  6.     char write_buf[] = "my first file";   
  7.     const int read_bytes = 8;   
  8.     char read_buf[read_bytes];   
  9.        
  10.     int fd = -1;   
  11.     fd = Open("/first_file",O_CREATE | O_RDWR);   
  12.     Assert(fd != -1);   
  13.     Printf("FD:%d/n",fd);   
  14.        
  15.     Assert(Write_File(fd,write_buf,Str_Len(write_buf)) != -1);   
  16.     Close(fd);   
  17.        
  18.     fd = -1;   
  19.     fd = Open("/first_file",O_RDWR);   
  20.     Assert(fd != -1);   
  21.     Printf("FD:%d/n",fd);   
  22.        
  23.     Assert(Read_File(fd,read_buf,read_bytes) != -1);   
  24.     read_buf[read_bytes] = '/0';   
  25.     Printf("Read File:%s/n",read_buf);   
  26.        
  27.     while(1)   
  28.     {      
  29.         //Milli_Delay(200);   
  30.         //Printf("%d ",Get_Ticks());   
  31.         Milli_Delay(200);   
  32.     }   
  33. }  

    OK,make,bochs,运行结果如下:

    嗯,这样看是成功了,还得看看硬盘里的数据,先看看这个文件在硬盘的哪个地方,通过查看该文件的i结点数组得到相对当前分区的扇区偏移为0x18e,这样得到相对整个硬盘的偏移字节数为:0x9dfe00+0x18e*512=0xa11a00,查看这个地儿:

 

    嗯,看到数据了,虽然没有很全面的测试,但起码这里没错,等到有人给我抓到BUG的时候再改吧。。

原创粉丝点击