|      |      |      |  否  |  否  |      |
| :--: | :--: | :--: | :--: | :--: | ---- |
**实现了哪些功能(已实现,并且测试正确的打勾)**
[√] 打印当前目录下所有文件和目录名,类似于ls简易版
[√] 打印文件/目录的文件控制块
[√] 打印整个文件分配表
[√] 切换目录,类似于cd功能
[√] 创建文件、删除文件
[√] 创建目录、删除文件
#### 2.ls简易版
##### 2.1 实现思路及伪代码
实现思路:使用`opendir`函数打开指定的路径,如果路径无效或者无法访问,`opendir`会返回NULL,此时打印错误信息并结束函数。然后使用`readdir`函数循环读取目录中的每一个条目,`readdir`函数在读取到目录末尾时会返回NULL,因此可以用它来控制循环的结束。在读取条目的过程中,如果条目的名称不是".“或”…“,就将其打印出来,”.“和”…"在Unix系统中分别代表当前目录和父目录,通常在列出目录内容时会被忽略。
```
定义函数 ls(path: 字符串)
### 操作系统实验——实现FAT12文件系统的关键知识点
#### 1. FAT12文件系统的概述
FAT12文件系统是一种较早的文件系统格式,主要用于较小的存储设备,如软盘等。其主要特点在于使用12位(即1.5字节)的簇号来表示文件分配表中的链表。由于每个簇号占用12位,FAT12文件系统最多可以支持\(2^{12} - 2 = 4094\)个簇(减去两个用于标记未使用的簇和坏簇的值)。这意味着在每簇大小为512字节的情况下,该文件系统最大可以支持大约2MB的存储空间。
#### 2. 实现的功能及技术细节
- **打印当前目录下所有文件和目录名**
  - **实现思路**:利用标准库函数`opendir`和`readdir`。`opendir`函数用于打开一个目录流,若成功则返回一个非空的DIR结构体指针;`readdir`函数则用于读取目录流中的目录项。
  - **伪代码**:
    ```c
    void ls(const char *path) {
        DIR *d;
        struct dirent *dir;
        d = opendir(path);
        if (d == NULL) {
            perror("opendir");
            return;
        }
        printf("内容如下:\n");
        while ((dir = readdir(d)) != NULL) {
            if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0)
                continue;
            printf("%s\n", dir->d_name);
        }
        closedir(d);
    }
    ```
  - **技术细节**:避免打印`.`和`..`这两个特殊目录,因为它们分别代表当前目录和父目录,通常在列出目录内容时被忽略。
- **打印文件/目录的文件控制块**
  - **实现思路**:读取磁盘上的文件控制块(FCB)信息,这些信息包含了文件的基本属性。
  - **伪代码**:
    ```c
    void print_FCB(struct root_dir_entry *root_dir, const char *disk, int offset, int root_ent_cnt) {
        int fd = open(disk, O_RDONLY);
        if (fd < 0) {
            perror("无法打开磁盘文件");
            return;
        }
        for (offset; offset <= offset + 32 * (root_ent_cnt - 1); offset += 32) {
            pread(fd, root_dir, sizeof(struct root_dir_entry), offset);
            if (root_dir->name[0] == 0xE5)
                continue;
            if (root_dir->name[0] == 0x00)
                break;
            printf("名称:");
            for (int i = 0; i < 8; i++)
                printf("%c", root_dir->name[i]);
            printf("\n扩展名:");
            // 打印扩展名
            printf("\n属性:");
            for (int i = 7; i >= 0; i--) {
                if ((root_dir->attributes & (1 << i)) != 0)
                    printf("%d", 1);
                else
                    printf("%d", 0);
            }
            printf("\n");
            // 其他字段的打印
        }
        close(fd);
    }
    ```
  - **技术细节**:文件控制块中的属性字段通常采用位字段的方式表示不同的属性标志,例如是否为只读、是否隐藏等。通过位操作来获取各个属性。
- **打印整个文件分配表**
  - **实现思路**:遍历文件分配表中的每一项,并打印出每个簇的状态。
  - **技术细节**:FAT12文件系统中的每个簇号使用12位表示,需要考虑如何正确地读取和解释这些簇号。
- **切换目录**
  - **实现思路**:通过改变当前工作目录来实现类似`cd`命令的功能。
  - **技术细节**:使用`chdir`函数可以更改当前工作目录,但需要注意权限问题。
- **创建文件、删除文件**
  - **实现思路**:利用系统调用`open`和`unlink`来实现。
  - **技术细节**:`open`函数可以用于创建新文件,而`unlink`函数则用于删除已存在的文件。
- **创建目录、删除文件**
  - **实现思路**:使用`mkdir`和`rmdir`函数。
  - **技术细节**:`mkdir`用于创建目录,`rmdir`用于删除空目录。注意`rmdir`只能删除空目录,如果要删除非空目录,则需要先删除目录中的所有文件和子目录。
#### 3. 测试过程及案例设计
- **测试用例**:设计多种测试场景,包括但不限于:
  - 测试空目录的情况。
  - 测试含有多个文件和子目录的目录。
  - 测试包含特殊文件名(如含有空格、特殊符号等)的文件或目录。
  - 测试文件或目录的创建、删除操作。
- **测试结果**:根据预期输出与实际输出的一致性来评估功能的正确性。
本实验不仅涵盖了基本的文件系统操作,还深入探讨了FAT12文件系统的工作原理及其实现细节,对于理解计算机操作系统底层机制具有重要意义。
                                    
                                    
                                         2025-05-27 15:03:27 
                                             26KB 
                                                操作系统
                                     
                                        
                                            1