《操作系统真象还原》第14章(下)

本篇博客对应书本14.11~14.15节


步骤:

1.创建目录

2.遍历目录

3.删除目录

4.任务的工作目录

5.获得文件属性


1.创建目录

①fs/fs.c,新增sys_mkdir()函数:

复制代码
  1 /* 创建目录pathname,成功返回0,失败返回-1 */
  2 int32_t sys_mkdir(const char* pathname){
  3     uint8_t rollback_step=0;   // 用于操作失败时回滚各资源状态
  4     void* io_buf=sys_malloc(SECTOR_SIZE*2);
  5     if (io_buf==NULL){
  6     printk("sys_mkdir: sys_malloc for io_buf failed\n");
  7     return -1;
  8     }
  9 
 10     struct path_search_record searched_record;
 11     memset(&searched_record,0,sizeof(struct path_search_record));
 12     int inode_no=-1;
 13     inode_no=search_file(pathname,&searched_record);
 14     if (inode_no!=-1){
 15     printk("sys_mkdir: file or directory %s exist!\n",pathname);
 16     rollback_step=1;
 17     goto rollback;
 18     }else {   // 若未找到,也要判断是在最终目录没找还是某个中间目录没找到
 19     uint32_t pathname_depth=path_depth_cnt((char*)pathname);
 20     uint32_t path_searched_depth=path_depth_cnt(searched_record.searched_path);
 21     /* 先判断是否把pathname的各层目录都访问到了,即是否在某个中间目录就失败了 */
 22     if (pathname_depth!=path_searched_depth){   // 说明没有访问到全部路径,即某个中间目录不存在
 23         printk("sys_mkdir: cannot access %s: Not a directory, subpath %s isn't exist\n",pathname,searched_record.searched_path);
 24         rollback_step=1;
 25         goto rollback;
 26     }
 27     }
 28 
 29     struct dir* parent_dir=searched_record.parent_dir;
 30     /* 目录名称后可能会有字符 '/',所以最好直接用searched_record.searched_path,无'/' */
 31     char* dirname=strrchr(searched_record.searched_path,'/')+1;
 32 
 33     inode_no=inode_bitmap_alloc(cur_part);
 34     if (inode_no==-1){
 35     printk("sys_mkdir: allocate inode failed\n");
 36     rollback_step=1;
 37     goto rollback;
 38     }
 39 
 40     struct inode new_dir_inode;
 41     inode_init(inode_no,&new_dir_inode);   // 初始化inode
 42 
 43     uint32_t block_bitmap_idx=0;   // 用来记录block对应于block_bitmap中的索引
 44     int32_t block_lba=-1;
 45     /* 为目录分配一个块,用来写入目录 . 和 .. */
 46     block_lba=block_bitmap_alloc(cur_part);
 47     if (block_lba==-1){
 48     printk("sys_mkdir: block_bitmap_alloc for create directory failed\n");
 49     rollback_step=2;
 50     goto rollback;
 51     }
 52     new_dir_inode.i_sectors[0]=block_lba;
 53     /* 每分配一个块就将位图同步到硬盘 */
 54     block_bitmap_idx=block_lba-cur_part->sb->data_start_lba;
 55     ASSERT(block_bitmap_idx!=0);
 56     bitmap_sync(cur_part,block_bitmap_idx,BLOCK_BITMAP);
 57 
 58     /* 将当前目录的目录项'.'和'..'写入目录 */
 59     memset(io_buf,0,SECTOR_SIZE*2);   // 情况io_buf
 60     struct dir_entry* p_de=(struct dir_entry*)io_buf;
 61 
 62     /* 初始化当前目录"." */
 63     memcpy(p_de->filename,".",1);
 64     p_de->i_no=inode_no;
 65     p_de->f_type=FT_DIRECTORY;
 66 
 67     ++p_de;
 68     /* 初始化当前目录".." */
 69     memcpy(p_de->filename,"..",2);
 70     p_de->i_no=parent_dir->inode->i_no;
 71     p_de->f_type=FT_DIRECTORY;
 72     ide_write(cur_part->my_disk,new_dir_inode.i_sectors[0],io_buf,1);
 73 
 74     new_dir_inode.i_size=2*cur_part->sb->dir_entry_size;
 75 
 76     /* 在父目录中添加自己的目录项 */
 77     struct dir_entry new_dir_entry;
 78     memset(&new_dir_entry,0,sizeof(struct dir_entry));
 79     create_dir_entry(dirname,inode_no,FT_DIRECTORY,&new_dir_entry);
 80     memset(io_buf,0,SECTOR_SIZE*2);   // 清空io_buf
 81     if (!sync_dir_entry(parent_dir,&new_dir_entry,io_buf)){
 82     printk("sys_mkdir: sync_dir_entry to disk failed\n");
 83     rollback_step=2;
 84     goto rollback;
 85     }
 86 
 87     /* 父目录的inode同步到硬盘 */
 88     memset(io_buf,0,SECTOR_SIZE*2);
 89     inode_sync(cur_part,parent_dir->inode,io_buf);
 90 
 91     /* 将新创建目录的inode同步到硬盘 */
 92     memset(io_buf,0,SECTOR_SIZE*2);
 93     inode_sync(cur_part,&new_dir_inode,io_buf);
 94 
 95     /* 将inode位图同步到硬盘 */
 96     bitmap_sync(cur_part,inode_no,INODE_BITMAP);
 97 
 98     sys_free(io_buf);
 99 
100     /* 关闭所创建目录的父目录 */
101     dir_close(searched_record.parent_dir);
102     return 0;
103 
104     /* 创建文件或目录需要创建相关的多个资源,若某步失败则hi执行到下面的回滚步骤 */
105 rollback:   // 回滚
106     switch(rollback_step){
107     case 2:
108         bitmap_set(&cur_part->inode_bitmap,inode_no,0);
109     case 1:
110         /* 关闭所创建目录的父目录 */
111         dir_close(searched_record.parent_dir);
112         break;
113     }
114     sys_free(io_buf);
115     return -1;
116 }
View Code
复制代码

更新一个我自己书写过程中的错误:在search_file()中第一个strcat()(约261行),应当与"/"相连接,而不是'/'。如果是'/',将为字符而非字符串,会出现错误,。之前竟然没有检测出来。。。

②fs/fs.h,增加一句函数声明:

int32_t sys_mkdir(const char* pathname);

③kernel/main.c:

复制代码
 1 int main(void){
 2     put_str("Welcome,\nI am kernel!\n");
 3     init_all();
 4     intr_enable();
 5     process_execute(u_prog_a, "u_prog_a");
 6     process_execute(u_prog_b, "u_prog_b");
 7     thread_start("k_thread_a", 31, k_thread_a, "I am thread_a");
 8     thread_start("k_thread_b", 31, k_thread_b, "I am thread_b");
 9 
10     printf("/dir1/subdir1 create %s!\n",sys_mkdir("/dir1/subdir1")==0?"done":"fail");
11     printf("/dir1 create %s!\n",sys_mkdir("/dir1")==0?"done":"fail");
12     printf("now, /dir1/subdir1 create %s!\n",sys_mkdir("/dir1/subdir1")==0?"done":"fail");
13     int fd=sys_open("/dir1/subdir1/file2",O_CREAT|O_RDWR);
14     if (fd!=-1){
15         printk("/dir1/subdir1/file2 create done!\n");
16         sys_write(fd,"Catch me if u can!\n",19);
17         sys_lseek(fd,0,SEEK_SET);
18         char buf[32]={0};
19         sys_read(fd,buf,19);
20         printf("/dir1/subdir1/file2 says:\n%s",buf);
21         sys_close(fd);
22     }
23 
24     while(1);
25     return 0;
26 }
View Code
复制代码

功能验证:

由于已经是第二次运行了,所以会看到/dir1、/dir1/subdir1和/file2 均创建失败的情况,不过可以发现它们其实是已经都exist了的。


2.遍历目录

先从开关目录开始。

①fs/fs.c,增加开关目录函数:

复制代码
 1 /* 目录打开成功后返回目录指针,失败返回NULL */
 2 struct dir* sys_opendir(const char* name){
 3     ASSERT(strlen(name)<MAX_PATH_LEN);
 4     /* 如果是根目录'.',直接返回&root_dir */
 5     if (name[0]=='/' && (name[1]==0 || name[0]=='.')){
 6     return &root_dir;
 7     }
 8 
 9     /* 先检查待打开的目录是否存在 */
10     struct path_search_record searched_record;
11     memset(&searched_record,0,sizeof(struct path_search_record));
12     int inode_no=search_file(name,&searched_record);
13     struct dir* ret=NULL;
14     if (inode_no==-1){   // 找不到目录
15     printk("In %s, sub path %s not exist\n, name, searched_record.searched_path");
16     }else {
17     if (searched_record.file_type==FT_REGULAR){
18         printk("%s is regular file!\n",name);
19     }else if (searched_record.file_type==FT_DIRECTORY){
20         ret=dir_open(cur_part,inode_no);
21     }
22     }
23     dir_close(searched_record.parent_dir);
24     return ret;
25 }
26 
27 /* 成功关闭目录p_dir返回0,失败返回-1 */
28 int32_t sys_closedir(struct dir* dir){
29     int32_t ret=-1;
30     if (dir!=NULL){
31     dir_close(dir);
32     ret=0;
33     }
34     return ret;
35 }
View Code
复制代码

②fs/fs.h,增加两句函数声明:

struct dir* sys_opendir(const char* name);
int32_t sys_closedir(struct dir* dir);

③kernel/main.c,还是修改main():

复制代码
 1 int main(void){
 2     put_str("Welcome,\nI am kernel!\n");
 3     init_all();
 4     intr_enable();
 5     process_execute(u_prog_a, "u_prog_a");
 6     process_execute(u_prog_b, "u_prog_b");
 7     thread_start("k_thread_a", 31, k_thread_a, "I am thread_a");
 8     thread_start("k_thread_b", 31, k_thread_b, "I am thread_b");
 9 
10     struct dir* p_dir=sys_opendir("/dir1/subdir1");
11     if (p_dir){
12     printf("/dir1/subdir1 open done!\n");
13     if (sys_closedir(p_dir)==0){
14         printf("/dir1/subdir1 close done!\n");
15     }else {
16         printf("/dir1/subdir1 close fail!\n");
17     }
18     }else {
19     printf("/dir1/subdir1 open fail!\n");
20     }
21 
22     while(1);
23     return 0;
24 }
View Code
复制代码

运行结果如图:

成功地open和close了文件目录。


然后尝试读取一个目录项:

④fs/dir.c,添加dir_read()函数:

复制代码
 1 /* 读取目录,成功返回一个目录项,失败返回NULL */
 2 struct dir_entry* dir_read(struct dir* dir){
 3     struct dir_entry* dir_e=(struct dir_entry*)dir->dir_buf; //哈哈 目录项里面自己有缓冲区
 4     struct inode* dir_inode=dir->inode;
 5     uint32_t all_blocks[140]={0},block_cnt=12;
 6     uint32_t block_idx=0,dir_entry_idx=0;
 7     while (block_idx<12){
 8         all_blocks[block_idx]=dir_inode->i_sectors[block_idx];
 9         ++block_idx;
10     }
11     if (dir_inode->i_sectors[12]!=0){
12         ide_read(cur_part->my_disk,dir_inode->i_sectors[12],all_blocks+12,1);
13         block_cnt=140;
14     }
15     block_idx=0;
16 
17     uint32_t cur_dir_entry_pos=0;   // 当前目录项的偏移
18     uint32_t dir_entry_size=cur_part->sb->dir_entry_size;
19     uint32_t dir_entrys_per_sec=SECTOR_SIZE/dir_entry_size;
20     /* 在目录大小内遍历 */
21     while (dir->dir_pos<dir_inode->i_size){
22         if(dir->dir_pos>=dir_inode->i_size){
23         return NULL;
24     }
25         if(all_blocks[block_idx]==0){
26             ++block_idx;
27             continue;
28         }
29         memset(dir_e,0,SECTOR_SIZE);
30         ide_read(cur_part->my_disk,all_blocks[block_idx],dir_e,1);
31         dir_entry_idx=0;
32     /* 遍历扇区内所有目录项 */
33         while (dir_entry_idx<dir_entrys_per_sec){
34             if ((dir_e + dir_entry_idx)->f_type){
35                 /* 已经遍历过 */
36                 if (cur_dir_entry_pos<dir->dir_pos){
37                     cur_dir_entry_pos+=dir_entry_size;
38                     ++dir_entry_idx;
39                     continue;
40                 }
41                 ASSERT(cur_dir_entry_pos==dir->dir_pos);
42                 dir->dir_pos+=dir_entry_size;   // 返回目录地址
43                 return dir_e+dir_entry_idx;
44             }
45             ++dir_entry_idx;
46         }
47         ++block_idx;
48     }
49     return NULL;
50 }
View Code
复制代码

⑤fs/dir.h,增加函数声明:

struct dir_entry* dir_read(struct dir* dir);

⑥kernel/main.c:

复制代码
 1 int main(void){
 2     put_str("Welcome,\nI am kernel!\n");
 3     init_all();
 4     intr_enable();
 5     process_execute(u_prog_a, "u_prog_a");
 6     process_execute(u_prog_b, "u_prog_b");
 7     thread_start("k_thread_a", 31, k_thread_a, "I am thread_a");
 8     thread_start("k_thread_b", 31, k_thread_b, "I am thread_b");
 9 
10     struct dir* p_dir=sys_opendir("/dir1/subdir1");
11     if (p_dir){
12         printf("/dir1/subdir1 open done!\ncontent:\n");
13         char* type=NULL;
14         struct dir_entry* dir_e=NULL;
15         while ((dir_e=sys_readdir(p_dir))){
16             if (dir_e->f_type==FT_REGULAR){
17             type="regular";
18             }else {
19                 type="directory";
20             }
21             printf("   %s   %s\n",type,dir_e->filename);
22         }
23         if (sys_closedir(p_dir)==0){
24             printf("/dir1/subdir1 close done!\n");
25         }else {
26             printf("/dir1/subdir1 close fail!\n");
27         }
28     }else {
29         printf("/dir1/subdir1 open fail!\n");
30     }
31 
32     while(1);
33     return 0;
34 }
View Code
复制代码

输出信息为:

输出了三个文件“.”和“..”和刚刚创建的普通文件“file2”。结束。


3.删除目录

①fs/dir.c,增加dir_is_empty()和dir_remove():

复制代码
 1 /* 判断目录是否为空 */
 2 bool dir_is_empty(struct dir* dir){
 3     struct inode* dir_inode=dir->inode;
 4     /* 若目录下只有'.'和'..'这两个目录项,则视为空 */
 5     return (dir_inode->i_size==cur_part->sb->dir_entry_size*2);
 6 }
 7 
 8 /* 在父目录parent_dir中删除child_dir */
 9 int32_t dir_remove(struct dir* parent_dir,struct dir* child_dir){
10     struct inode* child_dir_inode=child_dir->inode;
11     /* 空目录中只在inode->i_sectors[0]中有扇区,其它扇区都应该为空 */
12     int32_t block_idx=1;
13     while (block_idx<13){
14     ASSERT(child_dir_inode->i_sectors[block_idx]==0);
15     ++block_idx;
16     }
17     void* io_buf=sys_malloc(SECTOR_SIZE*2);
18     if (io_buf==NULL){
19     printk("dir_remove: malloc for io_buf failed!\n");
20     return -1;
21     }
22 
23     /* 在父目录parent_dir中删除子目录child_dir对应的目录项 */
24     delete_dir_entry(cur_part,parent_dir,child_dir_inode->i_no,io_buf);
25 
26     /* 回收inode中i_sectors中所占用的扇区,并同步inode_bitmap和block_bitmap */
27     inode_release(cur_part,child_dir_inode->i_no);
28     sys_free(io_buf);
29     return 0;
30 }
View Code
复制代码

②fs/dir.h,增加两个函数声明:

bool dir_is_empty(struct dir* dir);
int32_t dir_remove(struct dir* parent_dir,struct dir* child_dir);

③fs/fs.c,增加sys_rmdir():

复制代码
 1 /* 删除空目录,成功返回0,失败返回-1 */
 2 int32_t sys_rmdir(const char* pathname){
 3     /* 先检查要删除的文件是否存在 */
 4     struct path_search_record searched_record;
 5     memset(&searched_record,0,sizeof(struct path_search_record));
 6     int inode_no=search_file(pathname,&searched_record);
 7     ASSERT(inode_no!=0);
 8     int retval=-1;   // 默认return
 9     if (inode_no==-1){
10     printk("In %s, sub path %s not exist.\n",pathname,searched_record.searched_path);
11     }else {
12     if (searched_record.file_type==FT_REGULAR){
13         printk("%s is regular file!\n",pathname);
14     }else{
15         struct dir* dir=dir_open(cur_part,inode_no);
16         if (!dir_is_empty(dir)){
17         printk("dir %s is not empty, it is not allowed to delete noempty directory!\n",pathname);
18         }else {
19         if (!dir_remove(searched_record.parent_dir,dir)){
20             retval=0;
21         }
22         }
23         dir_close(dir);
24     }
25     }
26     dir_close(searched_record.parent_dir);
27     return retval;
28 }
View Code
复制代码

④fs/fs.h,增加一句函数声明:

int32_t sys_rmdir(const char* pathname);

⑤kernel/main.c,因为两对进程和线程的作用不大,所以我们忽略了:

复制代码
 1 int main(void){
 2     put_str("Welcome,\nI am kernel!\n");
 3     init_all();
 4 
 5     printf("/dir1 content before delete /dir1/subdir1:\n");
 6     struct dir* dir=sys_opendir("/dir1/");
 7     char* type=NULL;
 8     struct dir_entry* dir_e=NULL;
 9     while ((dir_e=sys_readdir(dir))){
10     if (dir_e->f_type==FT_REGULAR){
11         type="regular";
12     }else {
13         type="directory";
14     }
15     printf("   %s   %s\n",type,dir_e->filename);
16     }
17     printf("try to delete noempty directory /dir1/subdir1.\n");
18     if (sys_rmdir("/dir1/subdir1")==-1){
19     printf("sys_mrdir: /dir1/subdir1 delete fail!\n");
20     }
21 
22     printf("try to delete /dir1/subdir1/file2.\n");
23     if (sys_rmdir("/dir1/subdir1/file2")==-1){
24     printf("sys_rmdir: /dir1/subdir1/file2 delete fail!\n");
25     }
26     if (sys_unlink("/dir1/subdir1/file2")==0){
27     printf("sys_unlink: /dir1/subdir1/file2 delete done.\n");
28     }
29 
30     printf("try to delete directory /dir1/subdir1 again.\n");
31     if (sys_rmdir("/dir1/subdir1")==0){
32     printf("/dir1/subdir1 delete done.\n");
33     }
34 
35     printf("/dir1 content after delete /dir1/subdir1:\n");
36     sys_rewinddir(dir);
37     while ((dir_e=sys_readdir(dir))){
38     if (dir_e->f_type==FT_REGULAR){
39         type="regular";
40     }else {
41         type="directory";
42     }
43     printf("   %s   %s\n",type,dir_e->filename);
44     }
45 
46     while(1);
47     return 0;
48 }
View Code
复制代码

结果如下:


4.任务的工作目录

①fs/fs.c,直接将本节新增的四个函数一起放送出来:

复制代码
  1 /* 获得父目录的inode编号 */
  2 static uint32_t get_parent_dir_inode_nr(uint32_t child_inode_nr,void* io_buf){
  3     struct inode* child_dir_inode=inode_open(cur_part,child_inode_nr);
  4     /* 目录中的目录项".."中包括父目录inode编号,".."位于目录的第0块 */
  5     uint32_t block_lba=child_dir_inode->i_sectors[0];
  6     ASSERT(block_lba>=cur_part->sb->data_start_lba);
  7     inode_close(child_dir_inode);
  8     ide_read(cur_part->my_disk,block_lba,io_buf,1);
  9     struct dir_entry* dir_e=(struct dir_entry*)io_buf;
 10     /* 第0个目录项是".",第一个目录项是".." */
 11     ASSERT(dir_e[1].i_no<4096 && dir_e[1].f_type==FT_DIRECTORY);
 12     return dir_e[1].i_no;   // 返回..即父目录的inode编号
 13 }
 14 
 15 /* 在inode编号为p_inode_nr的目录中查找inode编号为c_inode_nr的子目录的名字,
 16  * 将名字存入缓冲区path.成功则返回0,失败返回-1 */
 17 static int get_child_dir_name(uint32_t p_inode_nr,uint32_t c_inode_nr,char* path,void* io_buf){
 18     struct inode* parent_dir_inode=inode_open(cur_part,p_inode_nr);
 19     /* 填充all_blocks,将该目录的所占扇区地址全部写入all_blocks */
 20     uint8_t block_idx=0;
 21     uint32_t all_blocks[140]={0},block_cnt=12;
 22     while (block_idx<12){
 23     all_blocks[block_idx]=parent_dir_inode->i_sectors[block_idx];
 24     ++block_idx;
 25     }
 26     if (parent_dir_inode->i_sectors[12]){
 27     ide_read(cur_part->my_disk,parent_dir_inode->i_sectors[12],all_blocks+12,1);
 28     block_cnt=140;
 29     }
 30     inode_close(parent_dir_inode);
 31 
 32     struct dir_entry* dir_e=(struct dir_entry*)io_buf;
 33     uint32_t dir_entry_size=cur_part->sb->dir_entry_size;
 34     uint32_t dir_entrys_per_sec=(512/dir_entry_size);
 35     block_idx=0;
 36     /* 遍历所有块 */
 37     while (block_idx<block_cnt){
 38     if (all_blocks[block_idx]){
 39         ide_read(cur_part->my_disk,all_blocks[block_idx],io_buf,1);
 40         uint8_t dir_e_idx=0;
 41         /* 遍历每个目录项 */
 42         while (dir_e_idx<dir_entrys_per_sec){
 43         if ((dir_e+dir_e_idx)->i_no==c_inode_nr){
 44             strcat(path,"/");
 45             strcat(path,(dir_e+dir_e_idx)->filename);
 46             return 0;
 47         }
 48         ++dir_e_idx;
 49         }
 50     }
 51     ++block_idx;
 52     }
 53     return -1;
 54 }
 55 
 56 /* 把当前工作目录绝对路径写入buf,size是buf的大小,
 57  * 当buf为NULL时,由操作系统分配存储工作路径的空间并返回地址,
 58  * 失败则返回NULL */
 59 char* sys_getcwd(char* buf,uint32_t size){
 60     /* 确保buf不为空,若用户进程提供的buf为NULL,
 61      * 系统调用getcwd中要为用户进程通过malloc分配内存 */
 62     ASSERT(buf!=NULL);
 63     void* io_buf=sys_malloc(SECTOR_SIZE);
 64     if (io_buf==NULL){
 65     return NULL;
 66     }
 67     struct task_struct* cur_thread=running_thread();
 68     int32_t parent_inode_nr=0;
 69     int32_t child_inode_nr=cur_thread->cwd_inode_nr;
 70     ASSERT(child_inode_nr>=0 && child_inode_nr<4096);
 71     /* 若当前目录是根目录,直接返回 '/' */
 72     if (child_inode_nr==0){
 73     buf[0]='/';
 74     buf[1]=0;
 75     sys_free(io_buf);
 76     return buf;
 77     }
 78 
 79     memset(buf,0,size);
 80     char full_path_reverse[MAX_PATH_LEN]={0};   // 用来作全路径缓冲区
 81 
 82     /* 从下往上逐层找父目录,直到找到根目录为止,
 83      * 当child_inode_nr为根目录的inode编号时停止,
 84      * 即已经查看完根目录中的目录项 */
 85     while ((child_inode_nr)){
 86     parent_inode_nr=get_parent_dir_inode_nr(child_inode_nr,io_buf);
 87     if (get_child_dir_name(parent_inode_nr,child_inode_nr,full_path_reverse,io_buf)==-1){
 88         sys_free(io_buf);
 89         return NULL;
 90     }
 91     child_inode_nr=parent_inode_nr;
 92     }
 93     ASSERT(strlen(full_path_reverse)<=size);
 94     /* 至此full_path_reverse中的路径是反的,
 95      * 即子目录在前,父目录在后
 96      * 现将full_path_reverse中的路径反向 */
 97     char* last_slash;   // 用于记录字符串中最后一个斜杠地址
 98     while ((last_slash=strrchr(full_path_reverse,'/'))){
 99     uint16_t len=strlen(buf);
100     strcpy(buf+len,last_slash);
101     /* 在full_path_reverse中添加结束字符,作为下一次执行strcpy中last_slash的边界 */
102     *last_slash=0;
103     }
104     sys_free(io_buf);
105     return buf;
106 }
107 
108 /* 更改当前工作目录为绝对路径path,成功则返回0,失败则返回-1 */
109 int32_t sys_chdir(const char* path){
110     int32_t ret=-1;
111     struct path_search_record searched_record;
112     memset(&searched_record,0,sizeof(struct path_search_record));
113     int inode_no=search_file(path,&searched_record);
114     if (inode_no!=-1){
115     if (searched_record.file_type==FT_DIRECTORY){
116         running_thread()->cwd_inode_nr=inode_no;
117         ret=0;
118     }else {
119         printk("sys_chdir: %s is regular file or other!\n",path);
120     }
121     }
122     dir_close(searched_record.parent_dir);
123     return ret;
124 }
View Code
复制代码

②fs/fs.h,以及它们各自的函数声明,因为有两个是static函数,所以只需要声明另外两个:

char* sys_getcwd(char* buf,uint32_t size);
int32_t sys_chdir(const char* path);

③thread/thread.h,在pcb中添加cwd_inode_nr属性:

④thread/thread.c,并在init_thread()中将nr初始化为0:

⑤kernel/main.c:

复制代码
 1 int main(void){
 2     put_str("Welcome,\nI am kernel!\n");
 3     init_all();
 4 
 5     char cwd_buf[32]={0};
 6     sys_getcwd(cwd_buf,32);
 7     printf("cwd: %s\n",cwd_buf);
 8     sys_chdir("/dir1");
 9     printf("change cwd now...\n");
10     sys_getcwd(cwd_buf,32);
11     printf("cwd: %s\n",cwd_buf);
12 
13     while(1);
14     return 0;
15 }
View Code
复制代码

运行结果:

这次简单,符合预期。


5.获得文件属性

①fs/fs.h,添加文件属性结构体和一句函数声明:

复制代码
struct stat{
    uint32_t st_ino;    // inode编号
    uint32_t st_size;   // inode尺寸
    enum file_types st_filetype;        // indoe文件类型
};

int32_t sys_stat(const char* path,struct stat* buf);
View Code
复制代码

②fs/fs.c,添加sys_stat(),以获取文件信息

复制代码
 1 /* 在buf中填充文件结构相关信息,成功返回0,失败返回-1 */
 2 int32_t sys_stat(const char* path,struct stat* buf){
 3     /* 若直接查看根目录 '.' */
 4     if (!strcmp(path,".") || !strcmp(path,"/.") || !strcmp(path,"/..")){
 5     buf->st_filetype=FT_DIRECTORY;
 6     buf->st_ino=0;
 7     buf->st_size=root_dir.inode->i_size;
 8     return 0;
 9     }
10 
11     int32_t ret=-1;   // 默认返回值
12     struct path_search_record searched_record;
13     memset(&searched_record,0,sizeof(struct path_search_record));
14     int inode_no=search_file(path,&searched_record);
15     if (inode_no!=-1){
16     struct inode* obj_inode=inode_open(cur_part,inode_no);   // 只为获得文件大小
17     buf->st_size=obj_inode->i_size;
18     inode_close(obj_inode);
19     buf->st_filetype=searched_record.file_type;
20     buf->st_ino=inode_no;
21     ret=0;
22     }else {
23     printk("sys_stat: %s not found\n",path);
24     }
25     dir_close(searched_record.parent_dir);
26     return ret;
27 }
View Code
复制代码

③kernel/main.c:

复制代码
 1 int main(void){
 2     put_str("Welcome,\nI am kernel!\n");
 3     init_all();
 4 
 5     struct stat obj_stat;
 6     sys_stat("/",&obj_stat);
 7     printf("/'s info\n i_no: %d\n size: %d\n filetype: %s\n", \
 8             obj_stat.st_ino,obj_stat.st_size, \
 9             obj_stat.st_filetype==2?"directory":"regular");
10     sys_stat("/dir1",&obj_stat);
11     printf("/dir1's info\n i_no: %d\n size: %d\n filetype: %s\n", \
12                     obj_stat.st_ino,obj_stat.st_size, \
13                     obj_stat.st_filetype==2?"directory":"regular");
14 
15     while(1);
16     return 0;
17 }
View Code
复制代码

运行结果:

额。。。似乎根目录的size有点问题,怎么会是408呢。。。先放着,后续再改进。不过历时约一星期,总算是把文件系统搞完了,要是把这么庞大的一章放在本书的开头,那不知道要劝退多少人:)


参考博客:

posted @   Hell0er  阅读(68)  评论(0编辑  收藏  举报
编辑推荐:
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示