【操作系统】磁盘文件管理系统

news2024/11/24 13:37:59

实验六  磁盘文件管理的模拟实现

  •  实验目的

文件系统是操作系统中用来存储和管理信息的机构,具有按名存取的功能,不仅能方便用户对信息的使用,也有效提高了信息的安全性。本实验模拟文件系统的目录结构,并在此基础上实现文件的各种操作方法。

通过本实验,深入理解文件和目录的作用和功能,熟悉与文件有关的系统调用,从而更好地掌握文件系统功能。

  •  实验内容

编程模拟实现磁盘文件管理。采用单级目录结构,存放用户的所有文件,系统提供创建文件、打开文件、读文件、写文件、关闭文件、删除文件命令。

(1)文件存储空间的分配采用位示图进行管理,该部分内容请参考实验5。磁盘信息如下:

现有一个磁盘组,共有8个柱面。每个柱面有4个磁道,每个磁道又划分成4个物理盘块,假设1个磁盘块大小为128B。磁盘的空间使用情况用位示图表示。位示图用若干个字构成,每一位对应一个磁盘块。“1”表示占用,“0”表示空闲。假定字长为16位,一个字可用来模拟磁盘的一个柱面。位示图的初始状态为第1个字为“1”,其他全部空闲。

(2)文件目录采用单级目录结构。整个文件系统中只建立一张文件目录表UFD,每个文件占一个目录项,目录项中含文件名、文件保护方式、文件长度等属性。

文件名

文件保护方式

文件当前长度

文件最大长度

文件所在地址

图1 用户文件目录表UFD

文件所在地址存放文件分配的磁盘块号。

文件保护方式:1表示文件可读,2表示文件可写,3表示文件可读写执行。

(3)系统建立一张用户打开文件表(UOF,用以记录系统当前正在使用的文件。假定最多允许打开4个文件,该表应设置4项。当打开文件个数超过4个时,应给出错误信息。用户打开文件表(UOF)的结构如下图所示。

图2 用户打开文件表(UOF)

图2中:

“文件操作方式”是指文件打开后要执行的操作

“状态”指用户打开文件表的各个表项为空表目或被占用。

读写指针用来指出对文件的存取位置。初始状态下,读指针=1,写指针=文件长度(追加写)。

(4)该文件系统提供6条命令:创建、打开、读、写、关闭、删除。各命令说明如下。

  • 创建一个文件,当用户要在磁盘上建立一个文件时,首先使用create命令向系统提出创建文件的请求:

fd= create(文件名,文件最大字节长度,文件保护方式);

例如:

fd= create(myfile1,200,2);

由文件最大长度计算出文件应占用的磁盘块数,然后为文件分配空间,并登记在用户文件目录表UFD中,同时登记在UOF表中。

不成功,返回-1; 成功返回文件描述符,即在UOF表中的序号。

  • 写文件命令 (文件描述符或文件名)

write(文件描述符或文件名,要写的字节个数);

例如:

write(myfile1,100);    模拟100个字节信息写入文件中。

不成功,返回-1,成功返回写入的字节个数

  • 打开文件命令

fd= open(文件描述符或文件名,操作方式); 

例如:fd=open(a.txt);

不成功,返回-1; 成功返回文件描述符,即在UOF表中的序号。

  • 读文件命令(选做)

read(文件描述符或文件名,要读的字节个数);

不成功,返回-1; 成功返回读取的字节个数

  • 关闭文件命令

close(文件描述符或文件名);

不成功,返回-1; 成功返回0

  • 删除文件命令

delete(文件名);

不成功,返回-1; 成功返回0

三. 测试用例

1】创建文件,记录各个数据结构情况

以下将创建6个文件,且包含3种文件保护方式,文件大小不完全相同。

(1)创建文件f1,文件大小 = 5,文件保护方式 = 3。

(2)创建文件f2,文件大小 = 5,文件保护方式 = 3。

(3)创建文件f3,文件大小 = 10,文件保护方式 = 3。

(4)创建文件f4,文件大小 = 5,文件保护方式 = 1。

(5)创建文件f5,文件大小 = 5,文件保护方式 = 3。

(6)创建文件f6,文件大小 = 5,文件保护方式 = 2。

上述文件创建完毕后,磁盘位示图和文件列表的情况如下图所示。

UOF为空状态,显示情况如下图所示。

2】读写文件,记录各个数据结构情况

在此步骤中,应该先打开文件,再对文件进行读/写操作,最后关闭文件。如果直接读/写文件,程序会提示相应报错。打开文件的操作序列如下所示。

(1)打开文件f1,文件操作方式 = 3。

(2)打开文件f2,文件操作方式 = 3。

(3)打开文件f3,文件操作方式 = 3。

(4)打开文件f4,文件操作方式 = 1。

(5)打开文件f5,文件操作方式 = 3。

由(5)可知,当打开文件数量大于4时,程序会提示打开文件数目超过上限,因此符合本实验中的【假定最多允许打开4个文件,该表应设置4项。当打开文件个数超过4个时,应给出错误信息】的要求。

此时UOF的情况如下图所示。

(6)读取文件f1,读取字节数 = 3。

此时UOF的情况如下图所示。可以发现f1文件的读指针有所修改。

(7)读取文件f2,读取字节数 = 10。

 由(7)可知,当从当前文件读指针开始,经过输入的读取字节数后,如果超过了文件的当前长度,程序会提示读取文件长度超过上限。

(8)写入文件f3,写入字节数 = 10。

此时UOF的情况如下图所示。可以发现f3文件的写指针、文件当前大小有所修改。

此时磁盘位示图的情况如下图所示。

(9)写入文件f4,写入字节数 = 5。

 由(9)可知,如果当前文件的保护方式与操作方式存在不兼容的情况,程序会提示该文件不能操作写。

(10)关闭文件f4。

(11)关闭文件f3。

此时UOF的情况如下图所示。可以发现f3文件和f4文件的信息已经不存在于UOF中,说明关闭操作成功。

此时磁盘位示图的情况如下图所示。可以发现文件依然存在于磁盘中,因此关闭操作并不会导致文件被删除的情况发生。

(12)关闭f2文件。

此时UOF的情况如下图所示。可以发现f2文件的信息已经不存在于UOF中,说明关闭操作成功。

(13)关闭f1文件。

此时UOF的情况如下图所示。可以发现f1文件的信息已经不存在于UOF中,说明关闭操作成功。

当前UOF为空,说明没有文件处于打开状态。

3】删除文件,记录各个数据结构情况

(1)删除f2文件。

此时磁盘位示图的情况如下图所示。可以发现f2文件的信息已经不存在于磁盘位示图中,说明删除操作成功。

(2)删除f3文件。

此时磁盘位示图的情况如下图所示。可以发现f3文件的信息已经不存在于磁盘位示图中,说明删除操作成功。

(3)删除f4文件。

此时磁盘位示图的情况如下图所示。可以发现f4文件的信息已经不存在于磁盘位示图中,说明删除操作成功。

后面将随机删除磁盘中剩余的各个文件,此处不再进行赘述。

4】所有的文件都删除掉时,磁盘恢复为初始化状态

四. 实验分析和总结

1】数据结构说明

(1)FCB的数据结构

FCB的代码实现如下图所示。

在本实验中,利用struct构造FileInfo结构体,实现对文件基本信息的记录,即文件控制块。

该数据结构的基本变量包括:文件名字的字符串file_name、文件大小的整型单变量file_size、文件分配扇区的一维数组allocated_sectors、文件保护方式的整型单变量protection。

(2)UOF的数据结构

UOF的代码实现如下图所示。

在本实验中,利用struct构造UOF结构体,实现对处于打开状态的各个文件进行记录,即用户文件打开表。

该数据结构的基本变量包括:文件名字的字符串file_name、文件操作方式的整型单变量protection、文件当前大小的整型单变量file_size、文件读指针的整型单变量read、文件写指针的整型单变量write、文件状态的整型单变量state(在本次实验中并没有实际用到)。

(3)磁盘空间的数据结构

磁盘空间的代码实现如下图所示。

在本实验中,利用struct构造StorageManager结构体,实现磁盘空间的初始化和管理,以及链接相应的文件信息。

该数据结构的基本变量包括:可用扇区总数的整型单变量available_sectors、磁盘位示图的二维数组bitmap、文件映射的哈希表files、打开文件映射的哈希表user。

该数据结构的功能包括:构造磁盘空间函数createFile、创建文件函数createFile、显示磁盘存储状态函数displayStatus、显示磁盘中的文件序列函数fileDetails、删除文件函数deleteFile、打开文件函数openFile、关闭文件函数closeFile、写入文件函数writeFile、读取文件函数readFile、显示UOF状态函数displayUOF。

2】程序流程图

1)主函数的程序流程图

2)构造磁盘空间函数的程序流程图

3)创建文件函数的程序流程图

4)显示磁盘存储状态函数的程序流程图

(5)显示磁盘中的文件序列函数的程序流程图

6)删除文件函数的程序流程图

7)打开文件函数的程序流程图(第一、二个判断框右侧为否,下测为是,画错)

8)关闭文件函数的程序流程图

9)写入文件函数的程序流程图

10)读取文件函数的程序流程图

11)显示UOF函数的程序流程图

3】程序运行结果,打印程序运行时的初值和运行结果

程序在测试用例下的运行结果如【三、测试用例】处所示。测试用例的流程图如下图所示。

4】实验知识点总结,实验收获与体会

1:单级文件目录是最简单的文件目录,只适用于单用户环境。在单级目录中,利用用户提供的文件名,用顺序查找法直接从文件目录中找到指名文件的目录项。
       其优点是:简单易实现,实现了“按名存取”。
       其缺点是:(1)查找速度慢。在目录文件中查找文件目录项需要时间长。②不允许重名。同一个目录中的文件不允许同名。③不便于实现文件共享。

2:两级目录结构由【主文件目录MFD】和【用户子目录UFD】组成。
       其优点是:①文件重名问题。每个用户可以使用相同的文件名。②提高了检索目录的速度。查找时间只是该用户所拥有的文件数目的一半时间,而不是所有文件的一半时间。③文件共享:允许不同用户使用不同文件名来访问同一个文件。原则上只要把对应的目录项指向同一物理位置的文件即可。
       其缺点是:用户不能对自己的文件进行分类管理。
       查找文件的逻辑结构如下图所示。

3:访问一个文件过程:根据文件名对目录进行查询,找出该文件的FCB或索引结点;

根据FCB中的盘块号,换算出物理地址,最后,把文件读进来。

4:在文件保护方式中,一共有3种状态。其中,1表示文件可读,2表示文件可写,3表示文件可读写执行。

5:在本次实验中,深入了解了文件系统的工作原理和如何模拟文件的创建、写入、打开、读取、关闭和删除等操作。同时,遇到了许多可能导致操作失败的情况,如磁盘空间不足、文件不存在、文件打开数超限等,因此学会了如何在程序中进行错误处理和返回适当的错误代码。

6:实验要求模拟文件系统,因此更加了解了系统调用的重要性。系统调用是用户程序与操作系统之间的桥梁,它允许用户程序与系统资源进行交互。同时,通过模拟用户打开文件表,学会了如何在系统中管理多个同时打开的文件,深入理解了多任务操作系统中的文件管理。

5】实验源代码

#include <iostream>

#include <vector>

#include <unordered_map>

using namespace std;

const int MAXOPEN = 4;

const int MAXBYTE = 50;

// FCB or one-UFD

struct FileInfo {  

    string file_name;               // 文件名字

    int file_size;                  // 文件大小

    vector<int> allocated_sectors;  // 文件分配的扇区

    int protection;                 // 文件保护方式

};

// UOF

struct UOF {

    string file_name;   //文件名字

    int protection;     //文件操作方式

    int file_size;      //文件大小 (当前)

    int read;           //文件读指针

    int write;          //文件写指针

    int state;          //文件状态

    //int file_path;        //文件地址 ,不如直接看磁盘。

};

// Disk

struct StorageManager {                    

    int available_sectors;                  // 可用扇区总数

    vector<vector<int>> bitmap;             // 磁盘位图

    unordered_map<string, FileInfo> files;  // 文件映射

    unordered_map<string, UOF> user;        // 打开文件映射

    StorageManager();                       // 构造函数yes

    bool createFile(const string&, int, int);   // 创建文件yes

    void displayStatus();                   // 显示存储状态yes

    void fileDetails(const FileInfo&);      // 显示文件详情yes

    bool deleteFile(const string&);         // 删除文件yes

   

    bool openFile(const string&, int);      // 打开文件,文件名+操作方式yes

    bool closeFile(const string&);          // 关闭文件,文件名yes

    bool writeFile(const string&, int);     // 写入文件,文件名+写入字节数yes

    bool readFile(const string&, int);      // 读取文件,文件名+读取字节数 yes

    void displayUOF();                      // 显示UOF

};

// show UOF

void StorageManager::displayUOF(){

    cout<<"文件打开表UOF:"<<endl;

    for(const auto& pair:user){

        cout<<pair.first<<"文件:";

        cout<<"[文件操作方式]"<<pair.second.protection<<"\t";

        cout<<"[文件当前大小]"<<pair.second.file_size<<"\t";

        cout<<"[文件读指针]"<<pair.second.read<<"\t";

        cout<<"[文件写指针]"<<pair.second.write<<"\t";

        cout<<"[文件状态]"<<pair.second.state;

        cout<<endl;

    }

}

// 读取文件

bool StorageManager::readFile(const string& name, int byte){

    auto it = user.find(name);

    if(it == user.end()){

        cout<<"读取文件错误:UOF里没有这个文件。"<<endl;

        return false;

    }

   

    UOF temp = it->second;

    if(temp.protection != 3 and temp.protection != 1){

        cout<<"读取文件错误:该文件不能操作读。"<<endl;

        return false;

    }

   

    if(temp.read + byte > temp.file_size){

        cout<<"读取文件错误:读取文件长度超过上限。"<<endl;

        return false;

    }

   

    // allow reading

    it->second.read += byte;

   

    return true;

}

// 写入文件

bool StorageManager::writeFile(const string& name, int byte){

    auto it = user.find(name);

    if(it == user.end()){

        cout<<"写入文件错误:UOF里没有这个文件。"<<endl;

        return false;

    }

   

    UOF temp = it->second;

    if(temp.protection != 3 and temp.protection != 2){

        cout<<"写入文件错误:该文件不能操作写。"<<endl;

        return false;

    }

   

    if(temp.write + byte > MAXBYTE){

        cout<<"写入文件错误:写入文件长度超过上限。"<<endl;

        return false;

    }

   

    // check disk

    if(available_sectors < byte){

        cout<<"写入文件错误:磁盘空间不足。"<<endl;

        return false;

    }

   

    auto find = files.find(name);

    FileInfo add = find->second;

   

    int addbyte = byte;

    // modify bitmap

    for(int i=0;i<bitmap.size()&&addbyte>0;++i){

        for(int j=0;j<bitmap[i].size()&&addbyte>0;++j){

            if(bitmap[i][j]==0){

                bitmap[i][j]=1;

                find->second.allocated_sectors.push_back(i*16+j);   //allocated_sectors

                --addbyte;

                --available_sectors;

            }

        }

    }

   

    // allow writing

    it->second.write += byte;       // 修改写指针

    it->second.file_size += byte;   // 修改当前文件长度

   

    // update FCB

    find->second.file_size += byte;

    fileDetails(find->second);

   

    return true;

}

// 关闭文件函数

bool StorageManager::closeFile(const string& name){

    auto it = user.find(name);

    if(it == user.end()){

        cout<<"关闭文件错误:UOF里没有这个文件。"<<endl;

        return false;

    }

   

    user.erase(it);

   

    return true;

}

// 打开文件函数

bool StorageManager::openFile(const string& name, int opt){

    auto it = files.find(name);

    if(it == files.end()){

        cout<<"打开文件错误:没有这个文件。"<<endl;

        return false;

    }

   

    FileInfo temp = it->second;

   

    if(temp.protection == 1){

        if(opt != 1){

            cout<<"打开文件错误:文件保护方式有限制。"<<endl;

            return false;

        }

    }

    else if(temp.protection == 2){

        if(opt != 2){

            cout<<"打开文件错误:文件保护方式有限制。"<<endl;

            return false;

        }

    }

   

    auto newit = user.find(name);

    if(newit != user.end()){

        cout<<"打开文件错误:这个文件已经打开。"<<endl;

        return false;

    }

   

    if(user.size() >= MAXOPEN){

        cout<<"打开文件错误:打开文件数目超过上限。"<<endl;

        return false;

    }

   

    // 文件名字、操作、当前大小、读ptr、写ptr、状态

    UOF t{name, opt, temp.file_size, 1, temp.file_size, 0};

    user[name] = t;     //hash setting

   

    return true;

}

// 构造函数  8个柱面。每个柱面有4个磁道,每个磁道又划分成4个物理盘块。

StorageManager::StorageManager() : available_sectors(128) {

    bitmap.resize(8, vector<int>(16, 0));   // 构造8*16个空盘块

    for (int j = 0; j < 16; ++j) {

        bitmap[0][j] = 1;  // 预留第一行作为系统文件,该柱面不可用

    }

}

// 创建文件函数

bool StorageManager::createFile(const string& name, int size, int protection) {

    if (files.find(name) != files.end()) {  // 如果文件名字不在末尾,则冲突

        cout << "创建文件错误: 文件已存在。"<< endl;

        return false;

    }  

    if (size > available_sectors) {     // 如果文件大小大于空闲扇区大小

        cout << "创建文件错误: 磁盘空间不足。"<< endl;

        return false;

    }

   

    // 创建新文件的FCB

    FileInfo newFile{ name, size, {} , protection};

   

    // 更新位示图中信息

    for (int i = 0; i < bitmap.size() && size > 0; ++i) {

        for (int j = 0; j < bitmap[i].size() && size > 0; ++j) {

            if (bitmap[i][j] == 0) {    // 如果这个盘块为空

                bitmap[i][j] = 1;   // 设置为已经分配

                newFile.allocated_sectors.push_back(i * 16 + j);    // 分配区增加这个盘块

                --size;     // 空闲区大小-=1

                --available_sectors;    // 同上

            }

        }

    }

    files[name] = newFile;  // hash表设置

    fileDetails(newFile);   // 显示新建文件详情

    return true;

}

// 显示磁盘分配情况函数

void StorageManager::displayStatus() {

    cout << "磁盘位图:" << endl;

    for (int i = 0; i < bitmap.size(); ++i) {

        for (int j = 0; j < bitmap[i].size(); ++j) {

            cout << bitmap[i][j] << ' ';

        }

        cout << endl;   // 换行显示

    }

   

    cout << endl << "文件列表:" << endl;

    for (const auto& pair : files) {

        cout <<"文件'"<< pair.first << "'的大小: " << pair.second.file_size << endl;

        fileDetails(pair.second);

    }

    cout << endl;

}

// 显示文件内存详情函数

void StorageManager::fileDetails(const FileInfo& file) {

    cout << "文件 '" << file.file_name << "' 的详细信息:"<< endl;

    for (int sector : file.allocated_sectors) {

        cout << "扇区: " << sector << ";";    //遍历扇区

    }

    cout << endl;

}

// 删除文件函数

bool StorageManager::deleteFile(const string& name) {

    auto it = files.find(name);

    if (it == files.end()) {

        cout << "删除文件错误: 文件不存在。"<< endl;

        return false;

    }

    for (int sector : it->second.allocated_sectors) {

        int i = sector / 16;

        int j = sector % 16;

        bitmap[i][j] = 0;

        ++available_sectors;

    }

    files.erase(it);

    auto another = user.find(name);

    if (another != user.end()){

        user.erase(another);

    }

   

    cout << "文件 '" << name << "' 已删除。"<< endl;

    return true;

}

// 菜单函数

void menu(StorageManager manager){

    cout << "根据数字提示选择操作: " << endl;

    cout << "0:退出系统,1:创建文件, 2:删除文件" << endl;

    cout << "4:打开文件,5:读取文件, 6:写入文件, 7:关闭文件" << endl;

    cout << "3:磁盘位示图,8:用户文件打开表"<<endl;

}

// 主函数

int main() {

    StorageManager manager;

    int action;

    string filename;

    int filesize;

    int protection;

    int byte;

    while (true) {

        bool flag = 1;

        cout << endl;

        menu(manager);

        cin >> action;

        cout << endl;

        switch (action) {

            // 1,创建文件

            case 1:

                cout << "输入文件名: ";

                cin >> filename;

                while (1){

                    cout << "输入文件大小: ";

                    cin >> filesize;

                    if(filesize<=0){

                        cout<<"文件大小必须为正,请重新输入!"<<endl;

                    }

                    else{

                        break;

                    }

                }

                while (1) {

                    cout << "输入文件保护方式:";

                    cin >> protection;

                    if(protection == 1 or protection == 2 or protection == 3){

                        break;

                    }

                    else{

                        cout<<"文件保护方式输入错误,请重新输入!"<<endl;

                    }

                }

                if (manager.createFile(filename, filesize, protection)) {

                    cout << "文件创建成功。"<<endl;

                }

                break;

            //2,删除文件

            case 2:

                cout << "输入要删除的文件名: ";

                cin >> filename;

                if (manager.deleteFile(filename)) {

                    cout << "文件删除成功。"<<endl;

                }

                break;

            //3,磁盘位示图

            case 3:

                manager.displayStatus();

                break;

            //4:打开文件

            case 4:

                cout << "输入要打开的文件名: ";

                cin >> filename;

                while(1){

                    cout<<"请输入文件操作方式:";

                    cin >> protection;

                    if(protection != 1 and protection != 2 and protection != 3){

                        cout<<"文件操作方式错误,请输入1、2、3中的其中一个。"<<endl;

                    }

                    else {

                        break;

                    }

                }

                if (manager.openFile(filename,protection)) {

                    cout << "文件打开成功。"<<endl;

                }

                break;

            //5:读取文件

            case 5:

                cout<<"输入要读取的文件名:";

                cin>>filename;

                while(1){

                    cout<<"输入要读取的字节数:";

                    cin>>byte;

                    if(byte <= 0){

                        cout<<"读取字节大小必须为正,请重新输入!"<<endl;

                    }

                    else{

                        break;

                    }

                }

                if(manager.readFile(filename, byte)){

                    cout<<"文件读取成功。"<<endl;

                }

                break;

            //6:写入文件

            case 6:

                cout<<"输入要写入的文件名:";

                cin>>filename;

                while(1){

                    cout<<"输入要写入的字节数:";

                    cin>>byte;

                    if(byte <= 0){

                        cout<<"写入字节大小必须为正,请重新输入!"<<endl;

                    }

                    else{

                        break;

                    }

                }

                if(manager.writeFile(filename, byte)){

                    cout<<"文件写入成功。"<<endl;

                }

                break;

            //7:关闭文件

            case 7:

                cout << "输入要关闭的文件名: ";

                cin >> filename;

                if(manager.closeFile(filename)){

                    cout << "文件关闭成功。"<<endl;

                }

                break;

            //8:UOF

            case 8:

                manager.displayUOF();

                break;

            case 0:

                cout << "程序退出,感谢使用。"<<endl;

                flag = 0;

                break;

            default:

                cout << "无效的数字操作,请重新输入。"<<endl;

                break;

        }

       

        if(!flag){

            break;

        }

    }

   

    return 0;

}

五.实验指导

1.  主要的数据结构(供参考)

UFD、UOF表可采用结构数组,也可采用链表方式,下面是结构数组方式的定义。

#define OPEN_FILE_MAX    4

#define FILE_NAME_MAX    20 

#define FILE_MAX      10   //系统中可创建的文件数量最大值

#define FILE_BLOCK_MAX      10   //文件磁盘块最大值

struct  FCB{

    // 文件控制块

    int    file_descriptor;            // 文件标识符

    char   file_name[FILE_NAME_MAX];  // 文件名

    int    protected_mode;             // 1:可读;2:可写;3:可读写执行

    int    file_current_length;          // 文件当前长度(字节)

    int    file_max_length;            // 文件最大长度(字节)

    // 以下是文件存储空间分配时产生的值,不需要用户定义

    int    length;                     // 文件的块数

    int    block[FILE_BLOCK_MAX];   // 存放文件的具体盘块号

    …….

}  UFD_table[FILE_MAX];  // UFD表信息,文件目录结构

struct  UOF{

    char file_name[FILE_NAME_MAX];

    int operate_mode;   // 打开后要执行的操作    1只读 2读写 3读写执行

    int read_pointer;   // 初始状态下为1

    int write_pointer;  // 初始状态下为文件长度

    int file_current_length;

    int file_path;

    int state;

} UOF_table[OPEN_FILE_MAX];       // 用户打开文件表

2. 文件系统执行流程

实验中,应先建立用户文件目录和用户打开文件表,然后给出一个菜单,请求用户选择要执行的操作。

(1)文件系统执行流程如下图所示。

2创建文件命令和流程图

fd= create(文件名,文件最大字节长度,文件保护方式)

3)写文件命令及其流程图

write(文件描述符或文件名,要写的字节个数);

4)打开文件命令及其流程图

fd= open(文件描述符或文件名,操作方式);

5读文件命令及其流程图

read(文件描述符或文件名,要读的字节个数);

6)关闭文件命令及其流程图

close(文件描述符或文件名);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1465596.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【服务器数据恢复】FreeNAS+ESXi虚拟机数据恢复案例

服务器数据恢复环境&#xff1a; 一台服务器通过FreeNAS&#xff08;本案例使用的是UFS2文件系统&#xff09;实现iSCSI存储&#xff0c;整个UFS2文件系统作为一个文件挂载到ESXi虚拟化系统&#xff08;安装在另外2台服务器上&#xff09;上。该虚拟化系统一共有5台虚拟机&…

Elasticsearch从入门到精通-01认识Elasticsearch

Elasticsearch从入门到精通-01认识Elasticsearch &#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是程序员行走的鱼 &#x1f342;博主从本篇正式开始ES学习&#xff0c;希望小伙伴可以一起探讨 &#x1f4d6; 本篇主要介绍和大家一块简单认识下ES并了解ES中的主要角色…

H5获取手机相机或相册图片两种方式-Android通过webview传递多张照片给H5

需求目的&#xff1a; 手机机通过webView展示H5网页&#xff0c;在特殊场景下&#xff0c;需要使用相机拍照或者从相册获取照片&#xff0c;上传后台。 完整流程效果&#xff1a; 如下图 一、H5界面样例代码 使用html文件格式&#xff0c;文件直接打开就可以展示布局&#…

爬虫知识--03

数据存mysql import requests from bs4 import BeautifulSoup import pymysql# 链接数据库pymysql conn pymysql.connect(userroot,password"JIAJIA",host127.0.0.1,databasecnblogs,port3306, ) cursor conn.cursor() cursor conn.cursor()# 爬数据 res request…

MaxScale实现mysql8读写分离

MaxScale 实验环境 中间件192.168.150.24MaxScale 22.08.4主服务器192.168.150.21mysql 8.0.30从服务器192.168.150.22mysql 8.0.30从服务器192.168.150.23mysql 8.0.30 读写分离基于主从同步 1.先实现数据库主从同步 基于gtid的主从同步配置 主库配置 # tail -3 /etc/my.…

Encoder-decoder 与Decoder-only 模型之间的使用区别

承接上文&#xff1a;Transformer Encoder-Decoer 结构回顾 笔者以huggingface T5 transformer 对encoder-decoder 模型进行了简单的回顾。 由于笔者最近使用decoder-only模型时发现&#xff0c;其使用细节和encoder-decoder有着非常大的区别&#xff1b;而huggingface的接口为…

【vue】provide/inject

provide/ inject这对选项需要一起使用&#xff0c;以允许一个祖先组件向其所有子孙后代注入一个依赖&#xff0c;不论组件层次有多深&#xff0c;并在起上下游关系成立的时间里始终生效。 通途点来讲可以用来实现隔代传值&#xff0c;传统的props只能父传子&#xff0c;而 prov…

Vue3实现页面顶部进度条

Vue3页面增加进度条 新建进度条组件新建bar.ts导航守卫中使用 Vue3项目使用导航守卫给页面增加进度条 新建进度条组件 loadingBar.vue <template><div class"wraps"><div ref"bar" class"bar"></div></div> <…

2.21日学习打卡----初学Nginx(一)

2.21日学习打卡 目录: 2.21日学习打卡一. Nginx是什么&#xff1f;概述Nginx 五大应用场景HTTP服务器正向代理反向代理正向代理与反向代理的区别&#xff1a;负载均衡动静分离 为啥使用Nginx? 二.下载Nginx&#xff08;linux&#xff09;环境准备下载Nginx和安装NginxNginx源码…

Redis高性能原理

redis大家都知道拥有很高的性能&#xff0c;每秒可以支持上万个请求&#xff0c;这里探讨下它高性能的原理。单线程架构和io多路复用技术。 一&#xff0c;单线程架构 单线程架构指的是命令执行核心线程是单线程的&#xff0c;数据持久化、同步、异步删除是其他线程在跑的。re…

代码随想录算法刷题训练营day22

代码随想录算法刷题训练营day22&#xff1a;LeetCode(236)二叉树的最近公共祖先、LeetCode(235) 二叉搜索树的最近公共祖先、LeetCode(701)二叉搜索树中的插入操作、LeetCode(450)删除二叉搜索树中的节点 LeetCode(236)二叉树的最近公共祖先 题目 代码 /*** Definition for…

springmvc基于springboot 的音乐播放系统 _7sdu8

这就意味着音乐播放系统的设计可以比其他系统更为出色的能力&#xff0c;可以更高效的完成最新的ymj排行榜、ymj音乐资讯等功能。 此系统设计主要采用的是JAVA语言来进行开发&#xff0c;JSP技术、采用SSM框架技术&#xff0c;框架分为三层&#xff0c;分别是控制层Controller&…

【生活】浅浅记录

各位小伙伴们好鸭&#xff0c;今天不是技术文章&#xff0c;浅浅记录一下最近几个月的收获&#x1f60a; 新的一年&#xff0c;一起努力&#xff0c;加油加油&#xff01;

航空航天5G智能工厂数字孪生可视化平台,推进航空航天数字化转型

航空航天5G智能工厂数字孪生可视化平台&#xff0c;推进航空航天数字化转型。随着科技的不断发展&#xff0c;数字化转型已经成为各行各业关注的焦点。航空航天业作为高端制造业的代表&#xff0c;也在积极探索数字化转型之路。为了更好地推进航空航天数字化转型&#xff0c;一…

Java项目:27 基于SSM+JSP实现的大学校园兼职平台

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统介绍 基于SSMJSP实现的大学校园兼职平台分为前台与管理员两块 管理端分为8大模块&#xff0c;分别是用户管理、兼职管理、帖子管理、聊天…

Python-pdfplumber读取PDF内容

文章目录 前言一、pdfplumber模块1.1 pdfplumber的特点1.2 pdfplumber.PDF类1.3pdfplumber.Page类 二 pdfplumber的使用2.1 加载PDF2.2 pdfplumber.PDF 类2.3 pdfplumber.Page 类2.4 读取PDF2.5 读取PDF文档信息2.6 查看总页数2.7 查看总页数读取第一页的宽度&#xff0c;页高等…

《论文阅读》通过识别对话中的情绪原因来提高共情回复的产生 EMNLP 2021

《论文阅读》通过识别对话中的情绪原因来提高共情回复的产生 EMNLP 2021 前言简介方法实现Emotion ReasonerResponse Generator实验结果示例总结前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦~ 无抄袭,无复制,纯手工敲击键盘~ 今天为大家带来的是《Improv…

Nginx 配置前端工程项目二级目录

前提&#xff1a; 前端工程技术框架: vue 后端工程技术工程&#xff1a;spring boot 需求&#xff1a;需要通过二级目录访问前端工程&#xff1a; 如之前&#xff1a;http://127.0.0.1:80/ 改成 http://127.0.0.1/secondDirectory:80/ 一.前端工程支持二级目录 1.编译文…

2.22 Qt day3 多界面跳转+qss登录界面优化+发布软件+对话框

思维导图&#xff1a; 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号…