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

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

  •  实验目的

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

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

  •  实验内容

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

(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.mzph.cn/news/696988.shtml

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

相关文章

FISCO BCOS(十七)利用脚本进行区块链系统监控

要利用脚本进行区块链系统监控&#xff0c;你可以使用各种编程语言编写脚本&#xff0c;如Python、Shell等 利用脚本进行区块链系统监控可以提高系统的稳定性、可靠性&#xff0c;并帮助及时发现和解决潜在问题&#xff0c;从而确保区块链网络的正常运行。本文可以利用脚本来解…

Vue3 使用动态组件 component

component 标签&#xff1a;用于动态渲染标签或组件。 语法格式&#xff1a; <component is"标签或组件名">标签内容</component> 动态渲染标签&#xff1a; <template><h3>我是父组件</h3><component is"h1">动态…

SpringCloud(15)之SpringCloud Gateway

一、Spring Cloud Gateway介绍 Spring Cloud Gateway 是Spring Cloud团队的一个全新项目&#xff0c;基于Spring 5.0、SpringBoot2.0、 Project Reactor 等技术开发的网关。旨在为微服务架构提供一种简单有效统一的API路由管理方式。 Spring Cloud Gateway 作为SpringCloud生态…

【Unity】MySql +Navicat 安装教程

问题描述 在使用Unity开发的时候&#xff0c;有的时候我们是需要使用Mysql数据库的&#xff0c;本教程使用的MySql 和Navicat均为免安装版 ❶mysql安装 1.下载mysql解压至任意目录&#xff0c;此处以“C:\mysql-5.6.39-winx64”为例. mysql百度云连接&#xff1a; 链接&…

Java的递归【详解】

1.认识递归基础知识 什么是方法递归&#xff1f; 递归是一种算法&#xff0c;在程序设计语言中广泛应用。 从形式上说&#xff1a;方法调用自身的形式称为方法递归&#xff08; recursion&#xff09;。 递归的形式&#xff1a; 直接递归&#xff1a;方法自己调用自己。 间接递…

【监控】Spring Boot+Prometheus+Grafana实现可视化监控

目录 1.概述 2.spring actuator 3.Prometheus 3.1.介绍 3.2.使用 1.client端的配置 2.server端的配置 4.grafana 5.留个尾巴 1.概述 本文是博主JAVA监控技术系列的第四篇&#xff0c;前面已经聊过了JMX、Spring actuator等技术&#xff0c;本文我们就将依托于Spring …

利用docker一键部署LLaMa到自己的Linux服务器,有无GPU都行、可以指定GPU数量、支持界面对话和API调用,离线本地化部署包含模型权重合并

利用docker一键部署LLaMa到自己的Linux服务器,有无GPU都行、可以指定GPU数量、支持界面对话和API调用,离线本地化部署包含模型权重合并。两种方式实现支持界面对话和API调用,一是通过搭建text-generation-webui。二是通过llamma.cpp转换模型为转换为 GGUF 格式,使用 quanti…

Leetcode日记 889. 根据前序和后序遍历构造二叉树

Leetcode日记 889. 根据前序和后序遍历构造二叉树 给定两个整数数组&#xff0c;preorder 和 postorder &#xff0c;其中 preorder 是一个具有 无重复 值的二叉树的前序遍历&#xff0c;postorder 是同一棵树的后序遍历&#xff0c;重构并返回二叉树。 如果存在多个答案&#…

petalinux_zynq7 驱动DAC以及ADC模块之二:petalinux

petalinux_zynq7 C语言驱动DAC以及ADC模块之一&#xff1a;建立IPhttps://blog.csdn.net/qq_27158179/article/details/136234296在上一篇&#xff0c;建立了ADC和DAC两个IP。这里继续。本文在 petalinux默认配置的基础上&#xff0c;添加了python和qt。再编译出sdk可以给x86主…

汽车智能座舱中 显示屏市场战略趋势分析 中篇

今天主要讲讲主流车厂显示屏的趋势。 主流车厂的中控&液晶仪表屏的尺寸及趋势汇总 奔驰 奔驰A级 10.2510.25 奔驰C级 12.310.25 奔驰GLA 10.2510.25 奔驰E级 12.312.3 奔驰S级 12.312.8 1、奔驰的仪表几乎都为液晶仪表&#xff0c;几乎所有车型都有HUD的选配&#xff…

大功率应用中的厚膜电阻散热器的设计?

在许多大功率应用中&#xff0c;例如电机和电源&#xff0c;电源电阻器位于主电源线中。它们的目的是防止损坏或提供一定程度的控制。 在这些应用中&#xff0c;电阻器承受恒定的、相对较高的电流。当电流流过电阻器时&#xff0c;它会产生热量。这种热能必须消散到环境中&…

1、WEB攻防-通用漏洞SQL注入MYSQL跨库ACCESS偏移

用途&#xff1a;个人学习笔记&#xff0c;欢迎指正&#xff01; 前言&#xff1a; 为了网站和数据库的安全性&#xff0c;MYSQL 内置有 ROOT 最高用户&#xff0c;划分等级&#xff0c;每个用户对应管理一个数据库&#xff0c;这样保证无不关联&#xff0c;从而不会影响到其他…

Autosar-WdgM配置详解-3

1.11生成代码解析 1.11.1MasterSWC代码解析 在MasterSWC的RE_TestRun这个runnable里会调用两个检测点函数,我们可以在两个检测点函数之间,加入我们所需要监控的代码。 Rte_Call_RPort_StartCheckPoint_CheckpointReached(); Rte_Call_RPort_EndCheckPoint_CheckpointReac…

C#串口 Modbus通讯工具类

一、安装Modbus包 二、创建modbushelper类 1、打开串口 public bool IfCOMOpend; //用于实例内的COM口的状态 public SerialPort OpenedCOM;//用于手动输入的COM转成SERIAL PORT /// <summary> /// 打开串口 /// </summary> /// <param name="COMname&quo…

c++服务器开源项目Tinywebserver运行

c服务器开源项目Tinywebserver运行 一、Tinywebserver介绍二、环境搭建三、构建数据库四、编译Tinywebserver五、查看效果 Tinywebserver是github上一个十分优秀的开源项目&#xff0c;帮助初学者学习如何搭建一个服务器。 本文讲述如何在使用mysql跟该项目进行连接并将项目运行…

python 层次分析(AHP)

文章目录 一、算法原理二、案例分析2.1 构建指标层判断矩阵2.2 求各指标权重2.2.1 算术平均法&#xff08;和积法&#xff09;2.2.2 几何平均法&#xff08;方根法&#xff09; 2.3 一致性检验2.3.1 求解最大特征根值2.3.2 求解CI、RI、CR值2.3.3 一致性判断 2.4 分别求解方案层…

利用Ubuntu22.04启动U盘对电脑磁盘进行格式化

概要&#xff1a; 本篇演示利用Ubuntu22.04启动U盘的Try Ubuntu模式对电脑磁盘进行格式化 一、说明 1、电脑 笔者的电脑品牌是acer(宏碁/宏基) 开机按F2进入BIOS 开机按F12进入Boot Manager 2、Ubuntu22.04启动U盘 制作方法参考笔者的文章&#xff1a; Ubuntu制作Ubun…

缓存篇—缓存雪崩

什么是缓存雪崩 通常我们为了保证缓存中的数据与数据库中的数据一致性&#xff0c;会给 Redis 里的数据设置过期时间&#xff0c;当缓存数据过期后&#xff0c;用户访问的数据如果不在缓存里&#xff0c;业务系统需要重新生成缓存&#xff0c;因此就会访问数据库&#xff0c;并…

QEMU源码全解析 —— virtio(22)

接前一篇文章&#xff1a;QEMU源码全解析 —— virtio&#xff08;21&#xff09; 前几回讲解了virtio驱动的加载。本回开始讲解virtio驱动的初始化。 在讲解virtio驱动的初始化之前&#xff0c;先要介绍virtio配置的函数集合变量virtio_pci_config_ops。实际上前文书也有提到…

万字干货-京东零售数据资产能力升级与实践

开篇 京东自营和商家自运营模式&#xff0c;以及伴随的多种运营视角、多种组合计算、多种销售属性等数据维度&#xff0c;相较于行业同等量级&#xff0c;数据处理的难度与复杂度都显著增加。如何从海量的数据模型与数据指标中提升检索数据的效率&#xff0c;降低数据存算的成…