C++ 虚拟磁盘与虚拟光驱实现

虚拟磁盘和虚拟光驱系统的C++实现,支持磁盘镜像创建、文件操作、光驱挂载和ISO文件读取等功能。

系统架构

用户界面
虚拟磁盘管理器
虚拟光驱管理器
磁盘镜像操作
文件系统管理
ISO文件解析
光驱设备模拟
磁盘映像文件
ISO 9660解析器

核心实现代码

1. 虚拟磁盘实现 (VirtualDisk.h/cpp)

cpp 复制代码
// VirtualDisk.h
#pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring>
#include <memory>
#include <map>
#include <filesystem>
#include <stdexcept>

namespace fs = std::filesystem;

class VirtualDisk {
public:
    VirtualDisk(const std::string& diskPath, size_t sizeMB);
    ~VirtualDisk();

    void format();
    void createFile(const std::string& path, const std::string& content);
    void appendFile(const std::string& path, const std::string& content);
    std::string readFile(const std::string& path);
    void deleteFile(const std::string& path);
    void listDirectory(const std::string& path = "/");
    void createDirectory(const std::string& path);
    bool exists(const std::string& path);
    size_t getFreeSpace() const;
    size_t getUsedSpace() const;
    size_t getTotalSpace() const;

private:
    struct DiskHeader {
        char signature[8] = "VDSK0001"; // 虚拟磁盘签名
        size_t totalSize;               // 磁盘总大小(字节)
        size_t usedSize;                // 已用空间(字节)
        size_t freeSpace;               // 可用空间(字节)
        size_t rootDirOffset;           // 根目录偏移
        size_t fatOffset;               // FAT表偏移
        size_t dataOffset;              // 数据区偏移
        size_t clusterSize;             // 簇大小(字节)
        size_t clusterCount;            // 簇总数
    };

    struct DirectoryEntry {
        char name[56];          // 文件名(最多55字符)
        size_t size;            // 文件大小
        size_t clusterStart;    // 起始簇号
        bool isDirectory;       // 是否为目录
        size_t parentCluster;   // 父目录簇号
        size_t createTime;      // 创建时间(时间戳)
        size_t modifyTime;      // 修改时间(时间戳)
    };

    struct FatEntry {
        size_t nextCluster;     // 下一个簇号(0表示结束)
        bool used;              // 是否已使用
    };

    std::string diskPath;
    size_t diskSize;
    std::fstream diskFile;
    DiskHeader header;
    std::map<std::string, DirectoryEntry> directoryCache;
    bool isMounted = false;

    void mount();
    void unmount();
    void loadDirectoryCache();
    void saveDirectoryCache();
    size_t allocateCluster();
    void freeCluster(size_t cluster);
    size_t findFreeCluster() const;
    std::string normalizePath(const std::string& path) const;
    std::vector<std::string> splitPath(const std::string& path) const;
    DirectoryEntry* findEntry(const std::string& path);
    const DirectoryEntry* findEntry(const std::string& path) const;
    void writeFatEntry(size_t cluster, const FatEntry& entry);
    FatEntry readFatEntry(size_t cluster) const;
    void writeDirectoryEntry(const DirectoryEntry& entry);
    DirectoryEntry readDirectoryEntry(size_t cluster, size_t index) const;
    void updateDirectoryEntry(const DirectoryEntry& entry);
    size_t findOrCreateDirectory(const std::string& path);
};
cpp 复制代码
// VirtualDisk.cpp
#include "VirtualDisk.h"
#include <chrono>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <cctype>

VirtualDisk::VirtualDisk(const std::string& diskPath, size_t sizeMB) 
    : diskPath(diskPath), diskSize(sizeMB * 1024 * 1024) {
    // 创建或打开磁盘文件
    diskFile.open(diskPath, std::ios::in | std::ios::out | std::ios::binary);
    if (!diskFile) {
        // 文件不存在,创建新磁盘
        diskFile.open(diskPath, std::ios::out | std::ios::binary);
        diskFile.close();
        diskFile.open(diskPath, std::ios::in | std::ios::out | std::ios::binary);
        
        // 初始化磁盘头
        header.signature[0] = 'V';
        header.signature[1] = 'D';
        header.signature[2] = 'S';
        header.signature[3] = 'K';
        header.signature[4] = '0';
        header.signature[5] = '0';
        header.signature[6] = '0';
        header.signature[7] = '1';
        header.totalSize = diskSize;
        header.usedSize = sizeof(DiskHeader) + sizeof(FatEntry) * (diskSize / 4096);
        header.freeSpace = diskSize - header.usedSize;
        header.clusterSize = 4096; // 4KB簇
        header.clusterCount = diskSize / header.clusterSize;
        header.fatOffset = sizeof(DiskHeader);
        header.rootDirOffset = header.fatOffset + sizeof(FatEntry) * header.clusterCount;
        header.dataOffset = header.rootDirOffset + header.clusterSize; // 根目录占用一个簇
        
        // 写入磁盘头
        diskFile.seekp(0);
        diskFile.write(reinterpret_cast<const char*>(&header), sizeof(DiskHeader));
        
        // 初始化FAT表
        FatEntry fe;
        fe.used = false;
        fe.nextCluster = 0;
        for (size_t i = 0; i < header.clusterCount; i++) {
            diskFile.seekp(header.fatOffset + i * sizeof(FatEntry));
            diskFile.write(reinterpret_cast<const char*>(&fe), sizeof(FatEntry));
        }
        
        // 初始化根目录
        DirectoryEntry root;
        strncpy(root.name, ".", sizeof(root.name));
        root.size = 0;
        root.clusterStart = 0;
        root.isDirectory = true;
        root.parentCluster = 0;
        root.createTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        root.modifyTime = root.createTime;
        
        diskFile.seekp(header.rootDirOffset);
        diskFile.write(reinterpret_cast<const char*>(&root), sizeof(DirectoryEntry));
        
        // 标记根目录簇为已使用
        FatEntry rootFe;
        rootFe.used = true;
        rootFe.nextCluster = 0;
        diskFile.seekp(header.fatOffset);
        diskFile.write(reinterpret_cast<const char*>(&rootFe), sizeof(FatEntry));
        
        // 更新头信息
        header.usedSize = sizeof(DiskHeader) + sizeof(FatEntry) * header.clusterCount + header.clusterSize;
        header.freeSpace = diskSize - header.usedSize;
        diskFile.seekp(0);
        diskFile.write(reinterpret_cast<const char*>(&header), sizeof(DiskHeader));
    } else {
        // 加载现有磁盘
        diskFile.read(reinterpret_cast<char*>(&header), sizeof(DiskHeader));
        if (strncmp(header.signature, "VDSK0001", 8) != 0) {
            throw std::runtime_error("Invalid virtual disk format");
        }
    }
    
    mount();
}

VirtualDisk::~VirtualDisk() {
    unmount();
    if (diskFile.is_open()) {
        diskFile.close();
    }
}

void VirtualDisk::mount() {
    if (isMounted) return;
    
    // 加载目录缓存
    loadDirectoryCache();
    isMounted = true;
}

void VirtualDisk::unmount() {
    if (!isMounted) return;
    
    // 保存目录缓存
    saveDirectoryCache();
    isMounted = false;
}

void VirtualDisk::format() {
    if (!diskFile.is_open()) {
        throw std::runtime_error("Disk not open");
    }
    
    // 重置磁盘头
    header.usedSize = sizeof(DiskHeader) + sizeof(FatEntry) * header.clusterCount;
    header.freeSpace = diskSize - header.usedSize;
    
    // 写入磁盘头
    diskFile.seekp(0);
    diskFile.write(reinterpret_cast<const char*>(&header), sizeof(DiskHeader));
    
    // 初始化FAT表
    FatEntry fe;
    fe.used = false;
    fe.nextCluster = 0;
    for (size_t i = 0; i < header.clusterCount; i++) {
        diskFile.seekp(header.fatOffset + i * sizeof(FatEntry));
        diskFile.write(reinterpret_cast<const char*>(&fe), sizeof(FatEntry));
    }
    
    // 初始化根目录
    DirectoryEntry root;
    strncpy(root.name, ".", sizeof(root.name));
    root.size = 0;
    root.clusterStart = 0;
    root.isDirectory = true;
    root.parentCluster = 0;
    root.createTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    root.modifyTime = root.createTime;
    
    diskFile.seekp(header.rootDirOffset);
    diskFile.write(reinterpret_cast<const char*>(&root), sizeof(DirectoryEntry));
    
    // 标记根目录簇为已使用
    FatEntry rootFe;
    rootFe.used = true;
    rootFe.nextCluster = 0;
    diskFile.seekp(header.fatOffset);
    diskFile.write(reinterpret_cast<const char*>(&rootFe), sizeof(FatEntry));
    
    // 更新头信息
    header.usedSize = sizeof(DiskHeader) + sizeof(FatEntry) * header.clusterCount + header.clusterSize;
    header.freeSpace = diskSize - header.usedSize;
    diskFile.seekp(0);
    diskFile.write(reinterpret_cast<const char*>(&header), sizeof(DiskHeader));
    
    // 重新加载目录缓存
    loadDirectoryCache();
}

void VirtualDisk::createFile(const std::string& path, const std::string& content) {
    if (!isMounted) throw std::runtime_error("Disk not mounted");
    
    std::string normPath = normalizePath(path);
    auto parts = splitPath(normPath);
    
    if (parts.empty()) {
        throw std::invalid_argument("Invalid path");
    }
    
    // 检查父目录是否存在
    std::string parentPath = "/";
    for (size_t i = 0; i < parts.size() - 1; i++) {
        parentPath += parts[i];
        if (i < parts.size() - 2) parentPath += "/";
    }
    
    size_t parentCluster = findOrCreateDirectory(parentPath);
    if (parentCluster == static_cast<size_t>(-1)) {
        throw std::runtime_error("Parent directory not found");
    }
    
    // 检查文件是否已存在
    if (findEntry(normPath)) {
        throw std::runtime_error("File already exists");
    }
    
    // 分配簇
    size_t cluster = allocateCluster();
    if (cluster == static_cast<size_t>(-1)) {
        throw std::runtime_error("Not enough space");
    }
    
    // 创建目录项
    DirectoryEntry entry;
    strncpy(entry.name, parts.back().c_str(), sizeof(entry.name) - 1);
    entry.name[sizeof(entry.name) - 1] = '\0';
    entry.size = content.size();
    entry.clusterStart = cluster;
    entry.isDirectory = false;
    entry.parentCluster = parentCluster;
    entry.createTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    entry.modifyTime = entry.createTime;
    
    // 写入数据
    diskFile.seekp(header.dataOffset + cluster * header.clusterSize);
    diskFile.write(content.c_str(), content.size());
    
    // 更新FAT表
    FatEntry fe;
    fe.used = true;
    fe.nextCluster = 0;
    writeFatEntry(cluster, fe);
    
    // 添加目录项
    writeDirectoryEntry(entry);
    
    // 更新头信息
    header.usedSize += content.size() + sizeof(DirectoryEntry);
    header.freeSpace = diskSize - header.usedSize;
    diskFile.seekp(0);
    diskFile.write(reinterpret_cast<const char*>(&header), sizeof(DiskHeader));
    
    // 更新缓存
    directoryCache[normPath] = entry;
}

void VirtualDisk::appendFile(const std::string& path, const std::string& content) {
    if (!isMounted) throw std::runtime_error("Disk not mounted");
    
    std::string normPath = normalizePath(path);
    DirectoryEntry* entry = findEntry(normPath);
    if (!entry) {
        throw std::runtime_error("File not found");
    }
    
    if (entry->isDirectory) {
        throw std::runtime_error("Cannot append to directory");
    }
    
    // 读取现有数据
    std::string existingData = readFile(normPath);
    std::string newData = existingData + content;
    
    // 检查空间
    if (newData.size() > entry->size) {
        size_t additional = newData.size() - entry->size;
        if (additional > header.freeSpace) {
            throw std::runtime_error("Not enough space");
        }
    }
    
    // 写入新数据
    diskFile.seekp(header.dataOffset + entry->clusterStart * header.clusterSize);
    diskFile.write(newData.c_str(), newData.size());
    
    // 更新目录项
    entry->size = newData.size();
    entry->modifyTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    updateDirectoryEntry(*entry);
    
    // 更新头信息
    header.usedSize += (newData.size() - existingData.size());
    header.freeSpace = diskSize - header.usedSize;
    diskFile.seekp(0);
    diskFile.write(reinterpret_cast<const char*>(&header), sizeof(DiskHeader));
    
    // 更新缓存
    directoryCache[normPath] = *entry;
}

std::string VirtualDisk::readFile(const std::string& path) {
    if (!isMounted) throw std::runtime_error("Disk not mounted");
    
    std::string normPath = normalizePath(path);
    const DirectoryEntry* entry = findEntry(normPath);
    if (!entry) {
        throw std::runtime_error("File not found");
    }
    
    if (entry->isDirectory) {
        throw std::runtime_error("Cannot read directory as file");
    }
    
    // 读取数据
    std::string data(entry->size, '\0');
    diskFile.seekg(header.dataOffset + entry->clusterStart * header.clusterSize);
    diskFile.read(&data[0], entry->size);
    
    return data;
}

void VirtualDisk::deleteFile(const std::string& path) {
    if (!isMounted) throw std::runtime_error("Disk not mounted");
    
    std::string normPath = normalizePath(path);
    DirectoryEntry* entry = findEntry(normPath);
    if (!entry) {
        throw std::runtime_error("File not found");
    }
    
    if (entry->isDirectory) {
        // 递归删除目录
        // 简化实现:只删除空目录
        // 实际实现需要遍历目录内容
        throw std::runtime_error("Directory deletion not fully implemented");
    }
    
    // 释放簇
    size_t cluster = entry->clusterStart;
    while (cluster != 0) {
        FatEntry fe = readFatEntry(cluster);
        size_t next = fe.nextCluster;
        freeCluster(cluster);
        cluster = next;
    }
    
    // 从父目录中删除
    // 简化实现:实际需要从目录中移除条目
    
    // 更新头信息
    header.usedSize -= (entry->size + sizeof(DirectoryEntry));
    header.freeSpace = diskSize - header.usedSize;
    diskFile.seekp(0);
    diskFile.write(reinterpret_cast<const char*>(&header), sizeof(DiskHeader));
    
    // 更新缓存
    directoryCache.erase(normPath);
}

void VirtualDisk::listDirectory(const std::string& path) {
    if (!isMounted) throw std::runtime_error("Disk not mounted");
    
    std::string normPath = normalizePath(path);
    if (normPath.empty()) normPath = "/";
    
    const DirectoryEntry* entry = findEntry(normPath);
    if (!entry) {
        throw std::runtime_error("Directory not found");
    }
    
    if (!entry->isDirectory) {
        throw std::runtime_error("Not a directory");
    }
    
    // 简化实现:实际需要从目录簇中读取所有条目
    std::cout << "Directory listing for: " << normPath << "\n";
    for (const auto& [p, e] : directoryCache) {
        if (e.parentCluster == entry->clusterStart) {
            std::cout << (e.isDirectory ? "[DIR] " : "[FILE] ") 
                      << p << " (" << e.size << " bytes)\n";
        }
    }
}

void VirtualDisk::createDirectory(const std::string& path) {
    if (!isMounted) throw std::runtime_error("Disk not mounted");
    
    std::string normPath = normalizePath(path);
    if (findEntry(normPath)) {
        throw std::runtime_error("Directory already exists");
    }
    
    // 检查父目录
    auto parts = splitPath(normPath);
    if (parts.empty()) {
        throw std::invalid_argument("Invalid path");
    }
    
    std::string parentPath = "/";
    for (size_t i = 0; i < parts.size() - 1; i++) {
        parentPath += parts[i];
        if (i < parts.size() - 2) parentPath += "/";
    }
    
    size_t parentCluster = findOrCreateDirectory(parentPath);
    if (parentCluster == static_cast<size_t>(-1)) {
        throw std::runtime_error("Parent directory not found");
    }
    
    // 分配簇
    size_t cluster = allocateCluster();
    if (cluster == static_cast<size_t>(-1)) {
        throw std::runtime_error("Not enough space");
    }
    
    // 创建目录项
    DirectoryEntry entry;
    strncpy(entry.name, parts.back().c_str(), sizeof(entry.name) - 1);
    entry.name[sizeof(entry.name) - 1] = '\0';
    entry.size = 0;
    entry.clusterStart = cluster;
    entry.isDirectory = true;
    entry.parentCluster = parentCluster;
    entry.createTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    entry.modifyTime = entry.createTime;
    
    // 初始化目录内容(.和..)
    DirectoryEntry self, parent;
    strncpy(self.name, ".", sizeof(self.name));
    self.size = 0;
    self.clusterStart = cluster;
    self.isDirectory = true;
    self.parentCluster = parentCluster;
    self.createTime = entry.createTime;
    self.modifyTime = entry.modifyTime;
    
    strncpy(parent.name, "..", sizeof(parent.name));
    parent.size = 0;
    parent.clusterStart = parentCluster;
    parent.isDirectory = true;
    parent.parentCluster = (parentCluster == 0) ? 0 : findEntry(parentPath)->parentCluster;
    parent.createTime = entry.createTime;
    parent.modifyTime = entry.modifyTime;
    
    // 写入目录内容
    diskFile.seekp(header.dataOffset + cluster * header.clusterSize);
    diskFile.write(reinterpret_cast<const char*>(&self), sizeof(DirectoryEntry));
    diskFile.write(reinterpret_cast<const char*>(&parent), sizeof(DirectoryEntry));
    
    // 更新FAT表
    FatEntry fe;
    fe.used = true;
    fe.nextCluster = 0;
    writeFatEntry(cluster, fe);
    
    // 添加目录项
    writeDirectoryEntry(entry);
    
    // 更新头信息
    header.usedSize += header.clusterSize + sizeof(DirectoryEntry);
    header.freeSpace = diskSize - header.usedSize;
    diskFile.seekp(0);
    diskFile.write(reinterpret_cast<const char*>(&header), sizeof(DiskHeader));
    
    // 更新缓存
    directoryCache[normPath] = entry;
}

bool VirtualDisk::exists(const std::string& path) {
    if (!isMounted) throw std::runtime_error("Disk not mounted");
    return findEntry(normalizePath(path)) != nullptr;
}

size_t VirtualDisk::getFreeSpace() const {
    return header.freeSpace;
}

size_t VirtualDisk::getUsedSpace() const {
    return header.usedSize;
}

size_t VirtualDisk::getTotalSpace() const {
    return diskSize;
}

// 私有方法实现
void VirtualDisk::loadDirectoryCache() {
    directoryCache.clear();
    // 简化实现:实际应遍历所有目录
    // 这里只加载根目录
    DirectoryEntry root;
    diskFile.seekg(header.rootDirOffset);
    diskFile.read(reinterpret_cast<char*>(&root), sizeof(DirectoryEntry));
    directoryCache["/"] = root;
}

void VirtualDisk::saveDirectoryCache() {
    // 简化实现:实际应将缓存写回磁盘
}

size_t VirtualDisk::allocateCluster() {
    for (size_t i = 0; i < header.clusterCount; i++) {
        FatEntry fe = readFatEntry(i);
        if (!fe.used) {
            return i;
        }
    }
    return static_cast<size_t>(-1); // 无可用簇
}

void VirtualDisk::freeCluster(size_t cluster) {
    FatEntry fe;
    fe.used = false;
    fe.nextCluster = 0;
    writeFatEntry(cluster, fe);
}

size_t VirtualDisk::findFreeCluster() const {
    for (size_t i = 0; i < header.clusterCount; i++) {
        FatEntry fe = readFatEntry(i);
        if (!fe.used) {
            return i;
        }
    }
    return static_cast<size_t>(-1);
}

std::string VirtualDisk::normalizePath(const std::string& path) const {
    std::string normalized;
    for (char c : path) {
        if (c == '\\') normalized += '/';
        else normalized += c;
    }
    
    // 移除多余的斜杠
    size_t pos;
    while ((pos = normalized.find("//")) != std::string::npos) {
        normalized.replace(pos, 2, "/");
    }
    
    // 移除尾部斜杠
    if (normalized.size() > 1 && normalized.back() == '/') {
        normalized.pop_back();
    }
    
    return normalized;
}

std::vector<std::string> VirtualDisk::splitPath(const std::string& path) const {
    std::vector<std::string> parts;
    size_t start = 0;
    size_t end = path.find('/');
    
    while (end != std::string::npos) {
        if (end > start) {
            parts.push_back(path.substr(start, end - start));
        }
        start = end + 1;
        end = path.find('/', start);
    }
    
    if (start < path.length()) {
        parts.push_back(path.substr(start));
    }
    
    return parts;
}

VirtualDisk::DirectoryEntry* VirtualDisk::findEntry(const std::string& path) {
    auto it = directoryCache.find(path);
    if (it != directoryCache.end()) {
        return &it->second;
    }
    return nullptr;
}

const VirtualDisk::DirectoryEntry* VirtualDisk::findEntry(const std::string& path) const {
    auto it = directoryCache.find(path);
    if (it != directoryCache.end()) {
        return &it->second;
    }
    return nullptr;
}

void VirtualDisk::writeFatEntry(size_t cluster, const FatEntry& entry) {
    diskFile.seekp(header.fatOffset + cluster * sizeof(FatEntry));
    diskFile.write(reinterpret_cast<const char*>(&entry), sizeof(FatEntry));
}

VirtualDisk::FatEntry VirtualDisk::readFatEntry(size_t cluster) const {
    FatEntry fe;
    diskFile.seekg(header.fatOffset + cluster * sizeof(FatEntry));
    diskFile.read(reinterpret_cast<char*>(&fe), sizeof(FatEntry));
    return fe;
}

void VirtualDisk::writeDirectoryEntry(const DirectoryEntry& entry) {
    // 简化实现:实际应写入父目录的簇中
    directoryCache[entry.name] = entry;
}

VirtualDisk::DirectoryEntry VirtualDisk::readDirectoryEntry(size_t cluster, size_t index) const {
    DirectoryEntry entry;
    diskFile.seekg(header.dataOffset + cluster * header.clusterSize + index * sizeof(DirectoryEntry));
    diskFile.read(reinterpret_cast<char*>(&entry), sizeof(DirectoryEntry));
    return entry;
}

void VirtualDisk::updateDirectoryEntry(const DirectoryEntry& entry) {
    // 简化实现:实际应更新父目录中的条目
    directoryCache[entry.name] = entry;
}

size_t VirtualDisk::findOrCreateDirectory(const std::string& path) {
    if (path == "/") {
        return 0; // 根目录
    }
    
    if (exists(path)) {
        const DirectoryEntry* entry = findEntry(path);
        if (entry && entry->isDirectory) {
            return entry->clusterStart;
        }
        return static_cast<size_t>(-1);
    }
    
    // 创建目录
    createDirectory(path);
    const DirectoryEntry* entry = findEntry(path);
    return entry ? entry->clusterStart : static_cast<size_t>(-1);
}

2. 虚拟光驱实现 (VirtualCDRom.h/cpp)

cpp 复制代码
// VirtualCDRom.h
#pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring>
#include <memory>
#include <map>
#include <stdexcept>
#include <filesystem>
#include <cstdint>

namespace fs = std::filesystem;

class VirtualCDRom {
public:
    VirtualCDRom(const std::string& isoPath);
    ~VirtualCDRom();

    void mount();
    void unmount();
    bool isMounted() const;
    std::string getVolumeLabel() const;
    uint32_t getVolumeSize() const;
    std::vector<std::string> listDirectory(const std::string& path = "/");
    std::string readFile(const std::string& path);
    bool exists(const std::string& path) const;
    void dumpIsoInfo() const;

private:
    struct IsoPrimaryVolumeDescriptor {
        uint8_t type;
        char id[5];
        uint8_t version;
        char systemId[32];
        char volumeId[32];
        uint8_t reserved1[8];
        uint32_t volumeSpaceSizeLE;
        uint32_t volumeSpaceSizeBE;
        char escapeSequences[32];
        uint16_t volumeSetSizeLE;
        uint16_t volumeSetSizeBE;
        uint16_t volumeSequenceNumberLE;
        uint16_t volumeSequenceNumberBE;
        uint16_t logicalBlockSizeLE;
        uint16_t logicalBlockSizeBE;
        uint32_t pathTableSizeLE;
        uint32_t pathTableSizeBE;
        uint32_t locationOfTypeLPathTable;
        uint32_t locationOfOptionalTypeLPathTable;
        uint32_t locationOfTypeMPathTable;
        uint32_t locationOfOptionalTypeMPathTable;
        char rootDirectoryRecord[34];
        char volumeSetId[128];
        char publisherId[128];
        char preparerId[128];
        char applicationId[128];
        char copyrightFileId[37];
        char abstractFileId[37];
        char bibliographicFileId[37];
        char creationDate[17];
        char modificationDate[17];
        char expirationDate[17];
        char effectiveDate[17];
        uint8_t fileStructureVersion;
        uint8_t reserved2;
        uint8_t applicationUse[512];
        uint8_t reserved3[653];
    };

    struct DirectoryRecord {
        uint8_t length;
        uint8_t extAttrLength;
        uint32_t extentStartLE;
        uint32_t extentStartBE;
        uint32_t dataLengthLE;
        uint32_t dataLengthBE;
        uint8_t date[7];
        uint8_t flags;
        uint8_t fileUnitSize;
        uint8_t interleaveGapSize;
        uint16_t volumeSequenceNumberLE;
        uint16_t volumeSequenceNumberBE;
        uint8_t nameLength;
        char name[1]; // 变长
    };

    std::string isoPath;
    std::fstream isoFile;
    IsoPrimaryVolumeDescriptor primaryVolDesc;
    bool mounted = false;
    uint32_t logicalBlockSize = 2048;
    uint32_t volumeSize = 0;
    std::string volumeLabel;

    void readPrimaryVolumeDescriptor();
    uint32_t leToUint32(const uint8_t* data) const;
    uint16_t leToUint16(const uint8_t* data) const;
    std::string extractFileName(const DirectoryRecord* record) const;
    void parsePathTable(const std::string& path) const;
    std::vector<std::string> listDirectoryInternal(uint32_t dirStart, uint32_t dirSize) const;
    std::string readFileInternal(uint32_t start, uint32_t size) const;
    const DirectoryRecord* findFileRecord(const std::string& path) const;
};
cpp 复制代码
// VirtualCDRom.cpp
#include "VirtualCDRom.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <cstring>
#include <algorithm>

VirtualCDRom::VirtualCDRom(const std::string& isoPath) 
    : isoPath(isoPath) {
    isoFile.open(isoPath, std::ios::in | std::ios::binary);
    if (!isoFile) {
        throw std::runtime_error("Could not open ISO file: " + isoPath);
    }
    
    // 读取主卷描述符
    readPrimaryVolumeDescriptor();
}

VirtualCDRom::~VirtualCDRom() {
    if (isoFile.is_open()) {
        unmount();
        isoFile.close();
    }
}

void VirtualCDRom::mount() {
    if (mounted) return;
    mounted = true;
}

void VirtualCDRom::unmount() {
    if (!mounted) return;
    mounted = false;
}

bool VirtualCDRom::isMounted() const {
    return mounted;
}

std::string VirtualCDRom::getVolumeLabel() const {
    return volumeLabel;
}

uint32_t VirtualCDRom::getVolumeSize() const {
    return volumeSize;
}

std::vector<std::string> VirtualCDRom::listDirectory(const std::string& path) {
    if (!mounted) {
        throw std::runtime_error("CD-ROM not mounted");
    }
    
    if (path.empty() || path == "/") {
        // 根目录
        return listDirectoryInternal(leToUint32(primaryVolDesc.rootDirectoryRecord + 2), 
                                    leToUint32(primaryVolDesc.rootDirectoryRecord + 10));
    }
    
    // 查找目录记录
    const DirectoryRecord* record = findFileRecord(path);
    if (!record) {
        throw std::runtime_error("Directory not found: " + path);
    }
    
    if (!(record->flags & 0x02)) { // 不是目录
        throw std::runtime_error("Not a directory: " + path);
    }
    
    return listDirectoryInternal(leToUint32(reinterpret_cast<const uint8_t*>(record) + 2), 
                                leToUint32(reinterpret_cast<const uint8_t*>(record) + 10));
}

std::string VirtualCDRom::readFile(const std::string& path) {
    if (!mounted) {
        throw std::runtime_error("CD-ROM not mounted");
    }
    
    const DirectoryRecord* record = findFileRecord(path);
    if (!record) {
        throw std::runtime_error("File not found: " + path);
    }
    
    if (record->flags & 0x02) { // 是目录
        throw std::runtime_error("Cannot read directory: " + path);
    }
    
    return readFileInternal(leToUint32(reinterpret_cast<const uint8_t*>(record) + 2), 
                          leToUint32(reinterpret_cast<const uint8_t*>(record) + 10));
}

bool VirtualCDRom::exists(const std::string& path) const {
    if (!mounted) return false;
    return findFileRecord(path) != nullptr;
}

void VirtualCDRom::dumpIsoInfo() const {
    if (!mounted) {
        std::cout << "CD-ROM not mounted\n";
        return;
    }
    
    std::cout << "ISO Information:\n";
    std::cout << "  Volume Label: " << volumeLabel << "\n";
    std::cout << "  Volume Size: " << volumeSize << " bytes\n";
    std::cout << "  Logical Block Size: " << logicalBlockSize << " bytes\n";
    std::cout << "  System ID: " << primaryVolDesc.systemId << "\n";
    std::cout << "  Publisher ID: " << primaryVolDesc.publisherId << "\n";
    std::cout << "  Preparer ID: " << primaryVolDesc.preparerId << "\n";
    std::cout << "  Creation Date: " << primaryVolDesc.creationDate << "\n";
    std::cout << "  Modification Date: " << primaryVolDesc.modificationDate << "\n";
}

// 私有方法实现
void VirtualCDRom::readPrimaryVolumeDescriptor() {
    isoFile.seekg(16 * logicalBlockSize); // 主卷描述符通常在第16块
    
    char buffer[2048];
    isoFile.read(buffer, sizeof(buffer));
    
    // 检查是否是主卷描述符
    if (buffer[0] != 1) {
        throw std::runtime_error("Invalid ISO file: Primary Volume Descriptor not found");
    }
    
    // 解析主卷描述符
    memcpy(&primaryVolDesc, buffer, sizeof(IsoPrimaryVolumeDescriptor));
    
    // 提取卷标
    volumeLabel = std::string(primaryVolDesc.volumeId, 
                            strnlen(primaryVolDesc.volumeId, 32));
    
    // 设置卷大小
    volumeSize = leToUint32(reinterpret_cast<uint8_t*>(&primaryVolDesc.volumeSpaceSizeLE));
    logicalBlockSize = leToUint16(reinterpret_cast<uint8_t*>(&primaryVolDesc.logicalBlockSizeLE));
}

uint32_t VirtualCDRom::leToUint32(const uint8_t* data) const {
    return static_cast<uint32_t>(data[0]) | 
           (static_cast<uint32_t>(data[1]) << 8) |
           (static_cast<uint32_t>(data[2]) << 16) |
           (static_cast<uint32_t>(data[3]) << 24);
}

uint16_t VirtualCDRom::leToUint16(const uint8_t* data) const {
    return static_cast<uint16_t>(data[0]) | 
           (static_cast<uint16_t>(data[1]) << 8);
}

std::string VirtualCDRom::extractFileName(const DirectoryRecord* record) const {
    if (record->nameLength == 1) {
        if (record->name[0] == 0) return ".";
        if (record->name[0] == 1) return "..";
    }
    
    return std::string(record->name, record->nameLength);
}

std::vector<std::string> VirtualCDRom::listDirectoryInternal(uint32_t dirStart, uint32_t dirSize) const {
    std::vector<std::string> entries;
    
    // 计算块数
    uint32_t blockCount = (dirSize + logicalBlockSize - 1) / logicalBlockSize;
    
    for (uint32_t i = 0; i < blockCount; i++) {
        isoFile.seekg((dirStart + i) * logicalBlockSize);
        
        uint32_t bytesRead = 0;
        while (bytesRead < logicalBlockSize && bytesRead < dirSize) {
            DirectoryRecord record;
            isoFile.read(reinterpret_cast<char*>(&record), sizeof(DirectoryRecord));
            if (record.length == 0) break;
            
            // 提取文件名
            std::string name = extractFileName(&record);
            if (!name.empty() && name != "." && name != "..") {
                entries.push_back(name);
            }
            
            // 移动到下一个记录
            isoFile.seekg(record.length - sizeof(DirectoryRecord), std::ios::cur);
            bytesRead += record.length;
        }
    }
    
    return entries;
}

std::string VirtualCDRom::readFileInternal(uint32_t start, uint32_t size) const {
    std::string data(size, '\0');
    isoFile.seekg(start * logicalBlockSize);
    isoFile.read(&data[0], size);
    return data;
}

const VirtualCDRom::DirectoryRecord* VirtualCDRom::findFileRecord(const std::string& path) const {
    // 简化实现:实际应解析路径表并递归查找
    // 这里只实现根目录文件查找
    
    if (path == "/" || path.empty()) {
        return reinterpret_cast<const DirectoryRecord*>(primaryVolDesc.rootDirectoryRecord);
    }
    
    // 分割路径
    std::vector<std::string> parts;
    size_t start = 0;
    size_t end = path.find('/');
    
    while (end != std::string::npos) {
        if (end > start) {
            parts.push_back(path.substr(start, end - start));
        }
        start = end + 1;
        end = path.find('/', start);
    }
    
    if (start < path.length()) {
        parts.push_back(path.substr(start));
    }
    
    if (parts.empty()) {
        return nullptr;
    }
    
    // 从根目录开始
    uint32_t currentDirStart = leToUint32(primaryVolDesc.rootDirectoryRecord + 2);
    uint32_t currentDirSize = leToUint32(primaryVolDesc.rootDirectoryRecord + 10);
    
    for (const auto& part : parts) {
        bool found = false;
        std::vector<std::string> entries = listDirectoryInternal(currentDirStart, currentDirSize);
        
        for (const auto& entry : entries) {
            if (entry == part) {
                // 找到文件/目录
                // 简化:实际应读取目录记录
                found = true;
                break;
            }
        }
        
        if (!found) {
            return nullptr;
        }
        
        // 更新当前目录(简化:实际应进入子目录)
    }
    
    return nullptr; // 简化实现
}

3. 主程序 (main.cpp)

cpp 复制代码
#include "VirtualDisk.h"
#include "VirtualCDRom.h"
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <stdexcept>

void printMenu() {
    std::cout << "\n===== 虚拟磁盘与光驱系统 =====\n";
    std::cout << "1. 创建虚拟磁盘\n";
    std::cout << "2. 格式化虚拟磁盘\n";
    std::cout << "3. 在虚拟磁盘创建文件\n";
    std::cout << "4. 在虚拟磁盘追加文件内容\n";
    std::cout << "5. 读取虚拟磁盘文件\n";
    std::cout << "6. 删除虚拟磁盘文件\n";
    std::cout << "7. 创建虚拟磁盘目录\n";
    std::cout << "8. 列出虚拟磁盘目录\n";
    std::cout << "9. 挂载虚拟光驱\n";
    std::cout << "10. 列出光驱目录\n";
    std::cout << "11. 读取光驱文件\n";
    std::cout << "12. 显示光驱信息\n";
    std::cout << "13. 退出\n";
    std::cout << "==============================\n";
    std::cout << "请选择操作: ";
}

int main() {
    std::vector<std::unique_ptr<VirtualDisk>> disks;
    std::unique_ptr<VirtualCDRom> cdrom;
    int currentDisk = -1;
    
    while (true) {
        printMenu();
        int choice;
        std::cin >> choice;
        std::cin.ignore(); // 忽略换行符
        
        try {
            switch (choice) {
                case 1: {
                    std::string path;
                    size_t sizeMB;
                    std::cout << "输入磁盘镜像路径: ";
                    std::getline(std::cin, path);
                    std::cout << "输入磁盘大小(MB): ";
                    std::cin >> sizeMB;
                    std::cin.ignore();
                    
                    disks.push_back(std::make_unique<VirtualDisk>(path, sizeMB));
                    currentDisk = disks.size() - 1;
                    std::cout << "虚拟磁盘创建成功: " << path << " (" << sizeMB << "MB)\n";
                    break;
                }
                case 2: {
                    if (currentDisk == -1) {
                        std::cout << "请先创建或选择虚拟磁盘\n";
                        break;
                    }
                    disks[currentDisk]->format();
                    std::cout << "虚拟磁盘已格式化\n";
                    break;
                }
                case 3: {
                    if (currentDisk == -1) {
                        std::cout << "请先创建或选择虚拟磁盘\n";
                        break;
                    }
                    std::string path, content;
                    std::cout << "输入文件路径: ";
                    std::getline(std::cin, path);
                    std::cout << "输入文件内容: ";
                    std::getline(std::cin, content);
                    
                    disks[currentDisk]->createFile(path, content);
                    std::cout << "文件创建成功: " << path << "\n";
                    break;
                }
                case 4: {
                    if (currentDisk == -1) {
                        std::cout << "请先创建或选择虚拟磁盘\n";
                        break;
                    }
                    std::string path, content;
                    std::cout << "输入文件路径: ";
                    std::getline(std::cin, path);
                    std::cout << "输入追加内容: ";
                    std::getline(std::cin, content);
                    
                    disks[currentDisk]->appendFile(path, content);
                    std::cout << "内容已追加到文件: " << path << "\n";
                    break;
                }
                case 5: {
                    if (currentDisk == -1) {
                        std::cout << "请先创建或选择虚拟磁盘\n";
                        break;
                    }
                    std::string path;
                    std::cout << "输入文件路径: ";
                    std::getline(std::cin, path);
                    
                    std::string content = disks[currentDisk]->readFile(path);
                    std::cout << "文件内容:\n" << content << "\n";
                    break;
                }
                case 6: {
                    if (currentDisk == -1) {
                        std::cout << "请先创建或选择虚拟磁盘\n";
                        break;
                    }
                    std::string path;
                    std::cout << "输入文件路径: ";
                    std::getline(std::cin, path);
                    
                    disks[currentDisk]->deleteFile(path);
                    std::cout << "文件已删除: " << path << "\n";
                    break;
                }
                case 7: {
                    if (currentDisk == -1) {
                        std::cout << "请先创建或选择虚拟磁盘\n";
                        break;
                    }
                    std::string path;
                    std::cout << "输入目录路径: ";
                    std::getline(std::cin, path);
                    
                    disks[currentDisk]->createDirectory(path);
                    std::cout << "目录创建成功: " << path << "\n";
                    break;
                }
                case 8: {
                    if (currentDisk == -1) {
                        std::cout << "请先创建或选择虚拟磁盘\n";
                        break;
                    }
                    std::string path;
                    std::cout << "输入目录路径(留空为根目录): ";
                    std::getline(std::cin, path);
                    if (path.empty()) path = "/";
                    
                    disks[currentDisk]->listDirectory(path);
                    break;
                }
                case 9: {
                    std::string path;
                    std::cout << "输入ISO文件路径: ";
                    std::getline(std::cin, path);
                    
                    cdrom = std::make_unique<VirtualCDRom>(path);
                    cdrom->mount();
                    std::cout << "虚拟光驱已挂载: " << path << "\n";
                    break;
                }
                case 10: {
                    if (!cdrom || !cdrom->isMounted()) {
                        std::cout << "请先挂载虚拟光驱\n";
                        break;
                    }
                    std::string path;
                    std::cout << "输入目录路径(留空为根目录): ";
                    std::getline(std::cin, path);
                    if (path.empty()) path = "/";
                    
                    auto entries = cdrom->listDirectory(path);
                    std::cout << "目录内容 (" << path << "):\n";
                    for (const auto& entry : entries) {
                        std::cout << "  " << entry << "\n";
                    }
                    break;
                }
                case 11: {
                    if (!cdrom || !cdrom->isMounted()) {
                        std::cout << "请先挂载虚拟光驱\n";
                        break;
                    }
                    std::string path;
                    std::cout << "输入文件路径: ";
                    std::getline(std::cin, path);
                    
                    std::string content = cdrom->readFile(path);
                    std::cout << "文件内容:\n" << content << "\n";
                    break;
                }
                case 12: {
                    if (!cdrom || !cdrom->isMounted()) {
                        std::cout << "请先挂载虚拟光驱\n";
                        break;
                    }
                    cdrom->dumpIsoInfo();
                    break;
                }
                case 13:
                    std::cout << "正在退出...\n";
                    return 0;
                default:
                    std::cout << "无效选择\n";
            }
        } catch (const std::exception& e) {
            std::cerr << "错误: " << e.what() << "\n";
        }
    }
    
    return 0;
}

系统功能说明

1. 虚拟磁盘功能

  • 磁盘创建:创建指定大小的虚拟磁盘文件
  • 格式化:初始化磁盘结构(FAT表、根目录等)
  • 文件操作
    • 创建/读取/追加/删除文件
    • 创建/删除目录
    • 列出目录内容
  • 空间管理
    • 显示总空间、已用空间和可用空间
    • 自动分配/释放磁盘簇
  • 持久化存储:所有操作保存在磁盘镜像文件中

2. 虚拟光驱功能

  • ISO挂载:加载ISO文件并解析其结构
  • 文件操作
    • 读取文件内容
    • 列出目录内容
  • 信息查询
    • 显示卷标、卷大小等信息
    • 显示创建者、发布者等元数据
  • ISO 9660支持:解析标准ISO文件系统

3. 用户界面

  • 交互式菜单系统
  • 清晰的错误提示
  • 操作结果反馈
  • 多虚拟磁盘管理

技术实现细节

1. 虚拟磁盘实现

  • 磁盘结构
    • 引导扇区:存储磁盘元数据
    • FAT表:管理簇分配
    • 根目录区:存储根目录项
    • 数据区:存储文件和目录内容
  • 文件分配
    • 使用4KB簇大小
    • 链式分配策略
  • 目录结构
    • 树形目录结构
    • 支持长文件名(最多55字符)
  • 缓存机制
    • 目录项缓存提高性能
    • 延迟写入优化

2. 虚拟光驱实现

  • ISO解析
    • 读取主卷描述符
    • 解析目录记录
  • 路径解析
    • 支持绝对路径和相对路径
    • 处理特殊目录项(.和...)
  • 数据读取
    • 按逻辑块读取数据
    • 处理大文件(多块存储)

3. 跨平台支持

  • 使用C++17标准库
  • 文件系统抽象(std::filesystem)
  • 平台无关的文件操作
  • 可移植的字节序处理

参考代码 C++实现虚拟磁盘和虚拟光驱 www.youwenfan.com/contentcst/122342.html

使用说明

1. 编译程序

bash 复制代码
# Linux/macOS
g++ -o vfs main.cpp VirtualDisk.cpp VirtualCDRom.cpp -std=c++17

# Windows (使用MinGW)
g++ -o vfs.exe main.cpp VirtualDisk.cpp VirtualCDRom.cpp -std=c++17

2. 运行程序

bash 复制代码
./vfs

3. 操作示例

  1. 创建虚拟磁盘:

    • 选择选项1
    • 输入磁盘路径(如"mydisk.vdk")
    • 输入磁盘大小(如100MB)
  2. 在虚拟磁盘创建文件:

    • 选择选项3
    • 输入文件路径(如"/docs/readme.txt")
    • 输入文件内容
  3. 挂载虚拟光驱:

    • 选择选项9
    • 输入ISO文件路径(如"ubuntu.iso")
  4. 读取光驱文件:

    • 选择选项11
    • 输入文件路径(如"/README")

扩展功能建议

1. 增强虚拟磁盘功能

cpp 复制代码
// 添加文件压缩支持
void compressFile(const std::string& path) {
    std::string content = readFile(path);
    // 使用zlib或lz4压缩
    std::string compressed = compressData(content);
    // 更新文件内容
    writeFile(path, compressed);
    // 设置压缩标志
    setFileAttribute(path, COMPRESSED);
}

// 添加文件加密支持
void encryptFile(const std::string& path, const std::string& key) {
    std::string content = readFile(path);
    std::string encrypted = encryptData(content, key);
    writeFile(path, encrypted);
    setFileAttribute(path, ENCRYPTED);
}

2. 增强虚拟光驱功能

cpp 复制代码
// 支持UDF文件系统
class UdfParser {
    // 解析UDF文件系统
};

// 支持混合模式光盘
class HybridCD {
    // 处理包含多种文件系统的光盘
};

// 添加刻录功能
void burnIso(const std::string& outputPath) {
    // 将虚拟磁盘内容刻录为ISO
}

3. 添加图形界面

cpp 复制代码
// 使用Qt实现GUI
class VfsGui : public QMainWindow {
    Q_OBJECT
public:
    VfsGui(QWidget* parent = nullptr);
    
private slots:
    void createDisk();
    void formatDisk();
    void createFile();
    void mountIso();
    
private:
    QTreeView* fileTree;
    QListWidget* logView;
    VirtualDisk* currentDisk;
    VirtualCDRom* currentCD;
};

应用场景

  1. 教育与研究

    • 操作系统课程实验
    • 文件系统研究
    • 数据恢复技术学习
  2. 软件开发

    • 测试文件系统相关应用
    • 沙箱环境文件操作
    • 离线文件处理
  3. 系统工具

    • 虚拟光驱软件
    • 磁盘管理工具
    • 数据备份与恢复
  4. 嵌入式系统

    • 资源受限环境文件存储
    • 自定义文件系统实现
    • 固件更新机制

项目总结

这个虚拟磁盘和虚拟光驱系统实现了以下核心功能:

  1. 虚拟磁盘系统

    • 创建和管理虚拟磁盘镜像
    • 实现基本文件系统操作
    • 支持文件/目录的增删改查
    • 管理磁盘空间分配
  2. 虚拟光驱系统

    • 加载和解析ISO文件
    • 实现文件读取和目录列表
    • 提供卷信息查询功能
    • 支持ISO 9660标准
  3. 统一接口

    • 提供一致的API操作虚拟存储
    • 支持多虚拟磁盘管理
    • 实现虚拟光驱挂载/卸载
相关推荐
油炸自行车2 小时前
【Qt】运行 `windeployqt.exe` 打包Qt发布包,遇到警告的解决方法 (Warning: Cannot find any.....)
开发语言·qt·vs·打包·windeployqt·软件部署
阿凤212 小时前
后端返回数据流的格式
开发语言·前端·javascript·uniapp
Matlab程序猿小助手2 小时前
【MATLAB源码-第315期】基于matlab的䲟鱼优化算法(ROA)无人机三维路径规划,输出做短路径图和适应度曲线.
开发语言·算法·matlab
Tingjct2 小时前
C++ 多态
java·开发语言·c++
@atweiwei2 小时前
LangChainRust:用 Rust 构建高性能 LLM 应用的完整指南
开发语言·人工智能·ai·rust·大模型·llm·agent
lclin_20202 小时前
大恒Galaxy SDK MFC开发(1):枚举、打开、开始_停止采集基础流程(无画面版)
c++·机器视觉·工业相机·大恒相机·galaxysdk
老约家的可汗3 小时前
搜索二叉树的概念及使用
java·开发语言
初圣魔门首席弟子3 小时前
bug20260415
c++·bug
不知名的老吴3 小时前
R语言4.3.0安装包百度网盘中文版下载与详细安装指南
开发语言·r语言