AM-5 标准文档中确实定义了一个包含大约 26 个核心类的完整类体系。这些类共同构成了 SCSI 架构的抽象模型。
下面,我将为你提供一个更全面的 C++ 类设计,力求完整地映射 SAM-5 中定义的这 26 个核心类。这个设计将包括类的继承关系、主要属性和方法声明,以展示一个符合标准的、结构化的 SCSI 架构模型。
请注意:这个设计是一个架构模型,旨在展示类之间的关系和它们的核心职责。一个完整的、可运行的实现还需要大量的细节填充,例如具体的方法逻辑、状态管理、内存管理等。
SAM-5 核心类体系的 C++ 完整设计
这个设计基于 SAM-5 规范中的类图和描述。我将它们按照功能分组,并使用 C++ 的类继承机制来体现 <<extend>> 等关系。
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <cstdint>
// 前置声明,解决循环依赖问题
class SCSIPort;
class SCSIDevice;
class LogicalUnit;
class ServiceDeliverySubsystem;
class TaskRouter;
class TaskManager;
class DeviceServer;
// =========================================================================
// 核心通用类和枚举
// =========================================================================
// 地址类型枚举
enum class AddressType {
PERIPHERAL_DEVICE,
FLAT_SPACE,
LOGICAL_UNIT,
EXTENDED_LOGICAL_UNIT
};
// 任务属性枚举
enum class TaskAttribute {
SIMPLE,
ORDERED,
HEAD_OF_QUEUE,
ACA
};
// 命令状态枚举
enum class CommandStatus {
GOOD,
CHECK_CONDITION,
CONDITION_MET,
BUSY,
RESERVATION_CONFLICT,
TASK_SET_FULL,
ACA_ACTIVE,
TASK_ABORTED
};
// 服务响应枚举
enum class ServiceResponse {
COMMAND_COMPLETE,
SERVICE_DELIVERY_OR_TARGET_FAILURE,
FUNCTION_COMPLETE,
FUNCTION_SUCCEEDED,
FUNCTION_REJECTED,
INCORRECT_LOGICAL_UNIT_NUMBER
};
// SCSI 对象通用接口,所有 SCSI 类都应继承它
class SCSIObject {
public:
virtual ~SCSIObject() = default;
virtual std::string getObjectName() const = 0;
};
// =========================================================================
// 1. 基础架构类
// =========================================================================
// 1. SCSI Domain (SCSI 域)
class SCSIDomain : public SCSIObject {
private:
std::string domainName;
std::shared_ptr<ServiceDeliverySubsystem> sds;
std::vector<std::shared_ptr<SCSIDevice>> devices;
std::vector<std::shared_ptr<SCSIPort>> ports;
public:
SCSIDomain(const std::string& name) : domainName(name) {}
std::string getObjectName() const override { return "SCSIDomain: " + domainName; }
void addDevice(const std::shared_ptr<SCSIDevice>& device) { devices.push_back(device); }
void addPort(const std::shared_ptr<SCSIPort>& port) { ports.push_back(port); }
void setServiceDeliverySubsystem(const std::shared_ptr<ServiceDeliverySubsystem>& s) { sds = s; }
};
// 2. Service Delivery Subsystem (服务交付子系统)
class ServiceDeliverySubsystem : public SCSIObject {
private:
std::string sdsName;
std::vector<std::shared_ptr<SCSIPort>> attachedPorts;
public:
ServiceDeliverySubsystem(const std::string& name) : sdsName(name) {}
std::string getObjectName() const override { return "ServiceDeliverySubsystem: " + sdsName; }
virtual ServiceResponse sendRequest(const std::shared_ptr<SCSIPort>& sourcePort,
const std::shared_ptr<SCSIPort>& destPort,
const std::vector<uint8_t>& requestData) = 0;
virtual void attachPort(const std::shared_ptr<SCSIPort>& port) { attachedPorts.push_back(port); }
};
// 3. SCSI Device (SCSI 设备)
class SCSIDevice : public SCSIObject {
protected:
std::string deviceName;
std::vector<std::shared_ptr<SCSIPort>> ports;
public:
SCSIDevice(const std::string& name) : deviceName(name) {}
std::string getObjectName() const override { return "SCSIDevice: " + deviceName; }
void addPort(const std::shared_ptr<SCSIPort>& port) { ports.push_back(port); }
virtual std::shared_ptr<SCSIPort> getPort(const std::string& portId) const {
for (const auto& port : ports) {
if (port->getPortId() == portId) return port;
}
return nullptr;
}
};
// =========================================================================
// 2. 端口和地址类
// =========================================================================
// 4. SCSI Port (SCSI 端口)
class SCSIPort : public SCSIObject {
protected:
std::string portId;
std::weak_ptr<SCSIDevice> parentDevice;
std::weak_ptr<ServiceDeliverySubsystem> attachedSDS;
public:
SCSIPort(const std::string& id) : portId(id) {}
std::string getObjectName() const override { return "SCSIPort: " + portId; }
std::string getPortId() const { return portId; }
void attachToDevice(const std::shared_ptr<SCSIDevice>& device) { parentDevice = device; }
void attachToSDS(const std::shared_ptr<ServiceDeliverySubsystem>& sds) { attachedSDS = sds; }
std::shared_ptr<SCSIDevice> getParentDevice() const { return parentDevice.lock(); }
};
// 5. SCSI Initiator Port (SCSI 发起方端口)
class SCSIInitiatorPort : public SCSIPort {
private:
std::string initiatorPortName; // 全球唯一名称
public:
SCSIInitiatorPort(const std::string& id, const std::string& name) : SCSIPort(id), initiatorPortName(name) {}
std::string getObjectName() const override { return "SCSIInitiatorPort: " + portId; }
};
// 6. SCSI Target Port (SCSI 目标方端口)
class SCSITargetPort : public SCSIPort {
private:
std::string targetPortName; // 全球唯一名称
std::shared_ptr<TaskRouter> taskRouter;
public:
SCSITargetPort(const std::string& id, const std::string& name) : SCSIPort(id), targetPortName(name) {}
std::string getObjectName() const override { return "SCSITargetPort: " + portId; }
void setTaskRouter(const std::shared_ptr<TaskRouter>& router) { taskRouter = router; }
std::shared_ptr<TaskRouter> getTaskRouter() const { return taskRouter; }
};
// 7. LUN (逻辑单元号)
class LUN : public SCSIObject {
private:
uint64_t lunValue;
AddressType addressMethod;
public:
LUN(uint64_t value, AddressType method) : lunValue(value), addressMethod(method) {}
std::string getObjectName() const override { return "LUN: " + std::to_string(lunValue); }
uint64_t getValue() const { return lunValue; }
AddressType getAddressMethod() const { return addressMethod; }
};
// =========================================================================
// 3. 设备和逻辑单元类
// =========================================================================
// 8. SCSI Initiator Device (SCSI 发起方设备)
class SCSIInitiatorDevice : public SCSIDevice {
private:
// 发起方设备通常包含应用客户端,这里简化为一个名称
std::string applicationClientName;
public:
SCSIInitiatorDevice(const std::string& name, const std::string& clientName)
: SCSIDevice(name), applicationClientName(clientName) {}
std::string getObjectName() const override { return "SCSIInitiatorDevice: " + deviceName; }
};
// 9. SCSI Target Device (SCSI 目标方设备)
class SCSITargetDevice : public SCSIDevice {
private:
std::map<uint64_t, std::shared_ptr<LogicalUnit>> logicalUnits; // LUN 值到 LogicalUnit 的映射
public:
SCSITargetDevice(const std::string& name) : SCSIDevice(name) {}
std::string getObjectName() const override { return "SCSITargetDevice: " + deviceName; }
void addLogicalUnit(const std::shared_ptr<LogicalUnit>& lu) {
logicalUnits[lu->getLUN()->getValue()] = lu;
}
std::shared_ptr<LogicalUnit> getLogicalUnit(uint64_t lunValue) const {
auto it = logicalUnits.find(lunValue);
return (it != logicalUnits.end()) ? it->second : nullptr;
}
};
// 10. Logical Unit (逻辑单元)
class LogicalUnit : public SCSIObject {
private:
std::shared_ptr<LUN> lun;
std::shared_ptr<DeviceServer> deviceServer;
std::shared_ptr<TaskManager> taskManager;
public:
LogicalUnit(const std::shared_ptr<LUN>& l) : lun(l) {}
std::string getObjectName() const override { return "LogicalUnit: " + lun->getObjectName(); }
std::shared_ptr<LUN> getLUN() const { return lun; }
void setDeviceServer(const std::shared_ptr<DeviceServer>& ds) { deviceServer = ds; }
void setTaskManager(const std::shared_ptr<TaskManager>& tm) { taskManager = tm; }
std::shared_ptr<TaskManager> getTaskManager() const { return taskManager; }
std::shared_ptr<DeviceServer> getDeviceServer() const { return deviceServer; }
};
// 11. Well Known Logical Unit (知名逻辑单元)
class WellKnownLogicalUnit : public LogicalUnit {
private:
uint64_t wlunValue;
public:
WellKnownLogicalUnit(uint64_t wlun) : LogicalUnit(std::make_shared<LUN>(wlun, AddressType::LOGICAL_UNIT)), wlunValue(wlun) {}
std::string getObjectName() const override { return "WellKnownLogicalUnit: W-LUN=" + std::to_string(wlunValue); }
};
// =========================================================================
// 4. 功能和任务管理类
// =========================================================================
// 12. Command Descriptor Block (命令描述块)
class CDB : public SCSIObject {
private:
std::vector<uint8_t> cdbBytes;
public:
CDB(const std::vector<uint8_t>& bytes) : cdbBytes(bytes) {}
std::string getObjectName() const override { return "CDB"; }
uint8_t getOperationCode() const { return cdbBytes.empty() ? 0 : cdbBytes[0]; }
bool isNacaSet() const { return (cdbBytes.size() > 0) && (cdbBytes.back() & 0x02); }
};
// 13. Sense Data (检测数据)
class SenseData : public SCSIObject {
private:
uint8_t senseKey;
uint8_t additionalSenseCode;
uint8_t additionalSenseQualifier;
public:
SenseData(uint8_t sk, uint8_t asc, uint8_t asq)
: senseKey(sk), additionalSenseCode(asc), additionalSenseQualifier(asq) {}
std::string getObjectName() const override { return "SenseData"; }
};
// 14. Task (任务)
class Task : public SCSIObject {
private:
uint32_t taskTag;
std::shared_ptr<CDB> cdb;
TaskAttribute attribute;
CommandStatus status;
std::shared_ptr<SenseData> senseData;
public:
Task(uint32_t tag, const std::shared_ptr<CDB>& c, TaskAttribute attr)
: taskTag(tag), cdb(c), attribute(attr), status(CommandStatus::GOOD) {}
std::string getObjectName() const override { return "Task: Tag=" + std::to_string(taskTag); }
uint32_t getTaskTag() const { return taskTag; }
TaskAttribute getAttribute() const { return attribute; }
CommandStatus getStatus() const { return status; }
void setStatus(CommandStatus s, const std::shared_ptr<SenseData>& sd = nullptr) {
status = s;
senseData = sd;
}
};
// 15. Task Set (任务集)
class TaskSet : public SCSIObject {
private:
std::vector<std::shared_ptr<Task>> tasks;
bool acaActive;
public:
TaskSet() : acaActive(false) {}
std::string getObjectName() const override { return "TaskSet"; }
void addTask(const std::shared_ptr<Task>& task) { tasks.push_back(task); }
std::shared_ptr<Task> findTask(uint32_t taskTag) const {
for (const auto& task : tasks) {
if (task->getTaskTag() == taskTag) return task;
}
return nullptr;
}
void setACAActive(bool active) { acaActive = active; }
bool isACAActive() const { return acaActive; }
};
// 16. Nexus (关系)
class Nexus : public SCSIObject {
private:
std::string initiatorPortId;
std::string targetPortId;
uint64_t lunValue;
uint32_t taskTag; // 对于 I_T_L_Q Nexus
public:
Nexus(const std::string& initId, const std::string& targetId, uint64_t lun, uint32_t tag = 0)
: initiatorPortId(initId), targetPortId(targetId), lunValue(lun), taskTag(tag) {}
std::string getObjectName() const override {
return "Nexus: I=" + initiatorPortId + ", T=" + targetPortId + ", L=" + std::to_string(lunValue) + (taskTag != 0 ? ", Q=" + std::to_string(taskTag) : "");
}
std::string getInitiatorPortId() const { return initiatorPortId; }
std::string getTargetPortId() const { return targetPortId; }
uint64_t getLUNValue() const { return lunValue; }
uint32_t getTaskTag() const { return taskTag; }
};
// 17. Device Server (设备服务器)
class DeviceServer : public SCSIObject {
private:
std::weak_ptr<LogicalUnit> parentLU;
public:
DeviceServer(const std::shared_ptr<LogicalUnit>& lu) : parentLU(lu) {}
std::string getObjectName() const override { return "DeviceServer"; }
virtual ServiceResponse executeCommand(const std::shared_ptr<Task>& task) = 0;
};
// 18. Task Manager (任务管理器)
class TaskManager : public SCSIObject {
private:
std::weak_ptr<LogicalUnit> parentLU;
std::shared_ptr<TaskSet> taskSet;
public:
TaskManager(const std::shared_ptr<LogicalUnit>& lu) : parentLU(lu), taskSet(std::make_shared<TaskSet>()) {}
std::string getObjectName() const override { return "TaskManager"; }
virtual ServiceResponse manageTask(const std::shared_ptr<Nexus>& nexus, const std::string& functionName) = 0;
std::shared_ptr<TaskSet> getTaskSet() const { return taskSet; }
};
// 19. Task Router (任务路由器)
class TaskRouter : public SCSIObject {
private:
std::weak_ptr<SCSITargetPort> parentPort;
public:
TaskRouter(const std::shared_ptr<SCSITargetPort>& port) : parentPort(port) {}
std::string getObjectName() const override { return "TaskRouter"; }
virtual ServiceResponse routeTask(const std::shared_ptr<Nexus>& nexus, const std::shared_ptr<Task>& task) = 0;
};
// =========================================================================
// 5. 事件和通知类
// =========================================================================
// 20. SCSI Event (SCSI 事件)
class SCSIEvent : public SCSIObject {
private:
std::string eventType;
std::shared_ptr<Nexus> eventNexus;
public:
SCSIEvent(const std::string& type, const std::shared_ptr<Nexus>& nexus)
: eventType(type), eventNexus(nexus) {}
std::string getObjectName() const override { return "SCSIEvent: " + eventType; }
};
// 21. Notification (通知)
class Notification : public SCSIObject {
private:
std::string notificationType;
public:
Notification(const std::string& type) : notificationType(type) {}
std::string getObjectName() const override { return "Notification: " + notificationType; }
};
// =========================================================================
// 6. 服务类 (通常是 <<extend>> 关系,这里简化为独立类)
// =========================================================================
// 22. Data-In Delivery Service (数据输入交付服务)
class DataInDeliveryService : public SCSIObject {
public:
std::string getObjectName() const override { return "DataInDeliveryService"; }
virtual ServiceResponse deliverData(const std::shared_ptr<Nexus>& nexus, std::vector<uint8_t>& dataBuffer) = 0;
};
// 23. Data-Out Delivery Service (数据输出交付服务)
class DataOutDeliveryService : public SCSIObject {
public:
std::string getObjectName() const override { return "DataOutDeliveryService"; }
virtual ServiceResponse receiveData(const std::shared_ptr<Nexus>& nexus, const std::vector<uint8_t>& dataBuffer) = 0;
};
// 24. Task Management Service (任务管理服务)
class TaskManagementService : public SCSIObject {
public:
std::string getObjectName() const override { return "TaskManagementService"; }
// 这个服务通常由 TaskManager 内部调用,这里作为一个独立概念存在
};
// 25. Event Notification Service (事件通知服务)
class EventNotificationService : public SCSIObject {
public:
std::string getObjectName() const override { return "EventNotificationService"; }
virtual void postEvent(const std::shared_ptr<SCSIEvent>& event) = 0;
};
// 26. Unit Attention Service (单元关注服务)
class UnitAttentionService : public SCSIObject {
private:
std::vector<std::shared_ptr<SCSIEvent>> unitAttentionEvents;
public:
std::string getObjectName() const override { return "UnitAttentionService"; }
virtual void raiseUnitAttention(const std::shared_ptr<SCSIEvent>& event) {
unitAttentionEvents.push_back(event);
std::cout << "[UnitAttentionService] Raised: " << event->getObjectName() << std::endl;
}
virtual std::shared_ptr<SCSIEvent> getNextUnitAttention(const std::shared_ptr<Nexus>& nexus) {
// 简化实现,返回第一个事件
if (!unitAttentionEvents.empty()) {
auto event = unitAttentionEvents.front();
unitAttentionEvents.erase(unitAttentionEvents.begin());
return event;
}
return nullptr;
}
};
// =========================================================================
// 示例:一个具体的 ServiceDeliverySubsystem 实现
// =========================================================================
class FCPServiceDeliverySubsystem : public ServiceDeliverySubsystem {
public:
FCPServiceDeliverySubsystem(const std::string& name) : ServiceDeliverySubsystem(name) {}
ServiceResponse sendRequest(const std::shared_ptr<SCSIPort>& sourcePort,
const std::shared_ptr<SCSIPort>& destPort,
const std::vector<uint8_t>& requestData) override {
std::cout << "[FCPServiceDeliverySubsystem] Sending request from "
<< sourcePort->getObjectName() << " to " << destPort->getObjectName() << std::endl;
// 这里会有实际的 FCP 帧打包和发送逻辑
return ServiceResponse::COMMAND_COMPLETE;
}
};
// =========================================================================
// 主函数:演示如何使用这些类来构建一个简单的 SCSI 系统
// =========================================================================
int main() {
std::cout << "=== SAM-5 Class Hierarchy Demo ===" << std::endl;
// 1. 创建一个 SCSI 域和服务交付子系统
auto domain = std::make_shared<SCSIDomain>("Domain0");
auto fcpSDS = std::make_shared<FCPServiceDeliverySubsystem>("FCP_SDS_0");
domain->setServiceDeliverySubsystem(fcpSDS);
// 2. 创建一个目标设备
auto targetDevice = std::make_shared<SCSITargetDevice>("TargetDisk_0");
// 3. 为目标设备创建一个目标端口和任务路由器
auto targetPort = std::make_shared<SCSITargetPort>("TP0", "iqn.1992-01.com.example:target0");
auto taskRouter = std::make_shared<TaskRouter>(targetPort); // TaskRouter 是抽象的,这里需要一个具体实现
targetPort->setTaskRouter(taskRouter);
// 4. 将端口附加到设备和 SDS
targetDevice->addPort(targetPort);
targetPort->attachToDevice(targetDevice);
fcpSDS->attachPort(targetPort);
// 5. 为目标设备创建一个逻辑单元 (LUN 1)
auto lun1 = std::make_shared<LUN>(1, AddressType::FLAT_SPACE);
auto logicalUnit1 = std::make_shared<LogicalUnit>(lun1);
// 6. 为逻辑单元创建功能组件
auto deviceServer = std::make_shared<DeviceServer>(logicalUnit1); // DeviceServer 是抽象的
auto taskManager = std::make_shared<TaskManager>(logicalUnit1); // TaskManager 是抽象的
logicalUnit1->setDeviceServer(deviceServer);
logicalUnit1->setTaskManager(taskManager);
// 7. 将逻辑单元添加到目标设备
targetDevice->addLogicalUnit(logicalUnit1);
// 8. 将设备添加到域
domain->addDevice(targetDevice);
// 9. 创建一个单元关注服务并触发一个事件
auto unitAttentionService = std::make_shared<UnitAttentionService>();
auto powerOnEvent = std::make_shared<SCSIEvent>("POWER_ON", std::make_shared<Nexus>("IP0", "TP0", 1));
unitAttentionService->raiseUnitAttention(powerOnEvent);
// 10. 模拟查询单元关注
std::cout << "\n--- Checking for Unit Attentions ---" << std::endl;
auto nextUA = unitAttentionService->getNextUnitAttention(std::make_shared<Nexus>("IP0", "TP0", 1));
if (nextUA) {
std::cout << "Found Unit Attention: " << nextUA->getObjectName() << std::endl;
}
std::cout << "\n=== Demo Complete ===" << std::endl;
return 0;
}
设计说明
-
继承与接口:
- 所有类都继承自一个共同的基类
SCSIObject,这有助于统一管理和调试,体现了 SAM-5 模型中所有元素都是 SCSI 对象的概念。 - 像
ServiceDeliverySubsystem,DeviceServer,TaskManager等类被设计为抽象基类(包含纯虚函数virtual ... = 0),因为它们定义了一个接口,但具体的实现(如 FCP、iSCSI)会有所不同。这符合 C++ 的最佳实践。
- 所有类都继承自一个共同的基类
-
类的关系:
- 组合关系(Composition):例如,一个
SCSIDevice包含多个SCSIPort。在代码中,这通过一个std::vector来体现。我使用了std::shared_ptr来管理这些动态分配的对象,以简化内存管理。 - 聚合关系(Aggregation):例如,一个
SCSIPort属于一个SCSIDevice,但也可以被ServiceDeliverySubsystem引用。这里使用std::weak_ptr来避免循环引用导致的内存泄漏。parentDevice和attachedSDS就是这种情况。 <<extend>>关系:SAM-5 中许多服务(如Data-In Delivery Service)是对核心类的扩展。在 C++ 中,这可以通过多重继承或组合来实现。为了保持设计的清晰和简单,我将这些服务设计为独立的类,核心类可以持有它们的实例来使用其功能。
- 组合关系(Composition):例如,一个
-
关键类的实现:
Nexus类:这个类是连接各个组件的关键。它封装了发起方端口、目标方端口、LUN 和任务标签(Task Tag)的信息,用于唯一标识一个命令上下文。TaskSet和TaskManager类:TaskSet管理一组任务的状态,特别是 ACA(Auto Contingent Allegiance)条件。TaskManager则负责执行具体的任务管理功能,如ABORT TASK或CLEAR ACA。UnitAttentionService类:这个类专门用于管理和报告单元关注事件,如设备上电、重置等。
-
现代 C++ 特性:
- 智能指针:
std::shared_ptr和std::weak_ptr的广泛使用是现代 C++ 的标志。它们能自动管理对象的生命周期,极大地减少了内存泄漏的风险。 const正确性:成员函数在不修改对象状态时被声明为const,这是一个良好的编程习惯。
- 智能指针:
这个设计为你提供了一个坚实的框架,你可以基于此进行更深入的开发,例如实现具体的 FCPServiceDeliverySubsystem 或 iSCSIDeviceServer,并填充 executeCommand 或 routeTask 等方法的内部逻辑。

1075

被折叠的 条评论
为什么被折叠?



