SAM-5 核心模型 C++ Demo 程序
以下 Demo 程序基于 SAM-5 标准的架构模型(SCSI 类、Nexus、LUN)、命令模型(命令执行、状态)、事件与通知模型、任务管理功能、任务集管理五大核心模块设计,通过面向对象思想封装关键组件,模拟 SCSI 设备的命令交互、任务管理与事件处理流程。
1. 头文件(SAM5_Core.h)
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <cstdint>
#include <algorithm>
// -------------------------- 通用枚举与常量定义 --------------------------
enum class CommandState {
NEW, // 新命令
DORMANT, // 休眠状态
ENABLED, // 启用状态
BLOCKED, // 阻塞状态(ACA 生效)
COMPLETED // 完成状态
};
enum class TaskAttribute {
SIMPLE, // 普通属性
ORDERED, // 有序属性
HEAD_OF_QUEUE, // 队列头部属性
ACA // ACA 专属属性
};
enum class CommandStatus {
GOOD, // 无错误完成
CHECK_CONDITION, // 需返回 Sense Data
BUSY, // 逻辑单元忙
RESERVATION_CONFLICT,// 预留冲突
TASK_SET_FULL, // 任务集资源不足
ACA_ACTIVE, // ACA 生效
TASK_ABORTED // 命令被中止
};
enum class ServiceResponse {
COMMAND_COMPLETE, // 命令完成
SERVICE_DELIVERY_OR_TARGET_FAILURE,// 服务交付失败
FUNCTION_COMPLETE, // 任务管理功能完成
FUNCTION_SUCCEEDED, // 任务管理功能成功
FUNCTION_REJECTED // 任务管理功能拒绝
};
enum class ScsiEvent {
POWER_ON, // 电源开启
HARD_RESET, // 硬重置
LOGICAL_UNIT_RESET,// 逻辑单元重置
I_T_NEXUS_LOSS, // I_T Nexus 丢失
POWER_LOSS_EXPECTED// 预期电源丢失
};
// -------------------------- 核心数据结构 --------------------------
struct SenseData {
uint8_t senseKey; // 错误键
uint8_t additionalSenseCode; // 附加错误码
uint8_t additionalSenseQualifier;// 附加错误限定符
std::string description; // 错误描述
SenseData() : senseKey(0), additionalSenseCode(0), additionalSenseQualifier(0) {}
SenseData(uint8_t sk, uint8_t asc, uint8_t asq, const std::string& desc)
: senseKey(sk), additionalSenseCode(asc), additionalSenseQualifier(asq), description(desc) {}
};
struct CDB {
uint8_t operationCode; // 操作码(命令类型)
uint8_t controlByte; // 控制字节(含 NACA 位)
std::vector<uint8_t> parameters; // 命令参数
bool isNacaSet() const {
return (controlByte & 0x02) != 0; // NACA 位为第 1 位(bit 1)
}
};
class LUN {
private:
uint64_t value; // 64 位 LUN 值
std::string addressMethod; // 寻址方式(peripheral/flat/extended)
public:
LUN(uint64_t val, const std::string& method) : value(val), addressMethod(method) {}
uint64_t getValue() const { return value; }
std::string getAddressMethod() const { return addressMethod; }
bool isValid() const {
return value != 0 && (addressMethod == "peripheral" || addressMethod == "flat" || addressMethod == "extended");
}
};
class Nexus {
public:
std::string initiatorPortId; // 发起方端口标识
std::string targetPortId; // 目标方端口标识
LUN* lun; // 逻辑单元(I_T_L/I_T_L_Q 需包含)
uint32_t commandId; // 命令标识(仅 I_T_L_Q 需包含)
// I_T Nexus(仅发起方+目标方端口)
Nexus(const std::string& initPort, const std::string& targetPort)
: initiatorPortId(initPort), targetPortId(targetPort), lun(nullptr), commandId(0) {}
// I_T_L Nexus(发起方+目标方端口+LUN)
Nexus(const std::string& initPort, const std::string& targetPort, LUN* l)
: initiatorPortId(initPort), targetPortId(targetPort), lun(l), commandId(0) {}
// I_T_L_Q Nexus(完整关系:含命令标识)
Nexus(const std::string& initPort, const std::string& targetPort, LUN* l, uint32_t cmdId)
: initiatorPortId(initPort), targetPortId(targetPort), lun(l), commandId(cmdId) {}
bool isITLQ() const { return lun != nullptr && commandId != 0; }
std::string getUniqueId() const {
std::string id = initiatorPortId + "-" + targetPortId;
if (lun != nullptr) id += "-" + std::to_string(lun->getValue());
if (commandId != 0) id += "-" + std::to_string(commandId);
return id;
}
};
// -------------------------- 事件监听接口(SAM-5 6.4) --------------------------
class IEventListener {
public:
virtual ~IEventListener() = default;
virtual void onEvent(ScsiEvent event, const Nexus& nexus) = 0; // 纯虚函数
};
// -------------------------- 命令类(SAM-5 5.1/8.5) --------------------------
class Command {
private:
Nexus itlqNexus; // I_T_L_Q Nexus(命令唯一标识)
CDB cdb; // 命令描述块
TaskAttribute attr; // 任务属性
CommandState state; // 命令状态
CommandStatus status;// 命令完成状态
SenseData senseData;// 错误/异常数据
uint32_t crn; // 命令参考号(I_T_L Nexus 内递增)
public:
Command(const Nexus& nexus, const CDB& c, TaskAttribute ta, uint32_t crnVal)
: itlqNexus(nexus), cdb(c), attr(ta), state(CommandState::NEW),
status(CommandStatus::GOOD), crn(crnVal) {}
std::string getUniqueId() const { return itlqNexus.getUniqueId(); }
TaskAttribute getTaskAttribute() const { return attr; }
CommandState getState() const { return state; }
void setState(CommandState s) { state = s; }
CommandStatus getStatus() const { return status; }
void setCompletionStatus(CommandStatus s, const SenseData& sd) {
status = s;
senseData = sd;
setState(CommandState::COMPLETED);
}
bool needEstablishACA() const { return cdb.isNacaSet(); }
uint8_t getOpCode() const { return cdb.operationCode; }
};
// -------------------------- 任务集类(SAM-5 4.6.23/8.9) --------------------------
class TaskSet {
private:
std::vector<Command*> commands; // 任务集中的命令
bool isACAActive; // ACA 是否生效
std::string itlNexusId; // 关联的 I_T_L Nexus ID
public:
TaskSet(const std::string& nexusId) : isACAActive(false), itlNexusId(nexusId) {}
~TaskSet() {
for (auto cmd : commands) delete cmd;
}
void addCommand(Command* cmd) {
if (isACAActive && cmd->getTaskAttribute() != TaskAttribute::ACA) {
cmd->setState(CommandState::BLOCKED);
} else {
switch (cmd->getTaskAttribute()) {
case TaskAttribute::SIMPLE:
case TaskAttribute::ORDERED:
cmd->setState(CommandState::DORMANT);
break;
case TaskAttribute::HEAD_OF_QUEUE:
case TaskAttribute::ACA:
cmd->setState(CommandState::ENABLED);
break;
}
}
commands.push_back(cmd);
std::cout << "[TaskSet] 命令 " << cmd->getUniqueId() << " 添加到任务集 " << itlNexusId << std::endl;
}
Command* findCommand(const std::string& cmdUniqueId) {
for (auto cmd : commands) {
if (cmd->getUniqueId() == cmdUniqueId) return cmd;
}
return nullptr;
}
ServiceResponse abortCommand(const std::string& cmdUniqueId) {
Command* cmd = findCommand(cmdUniqueId);
if (!cmd) return ServiceResponse::FUNCTION_COMPLETE;
cmd->setCompletionStatus(CommandStatus::TASK_ABORTED, SenseData(0x0B, 0x00, 0x00, "Command aborted by task management"));
std::cout << "[TaskSet] 命令 " << cmdUniqueId << " 已中止" << std::endl;
return ServiceResponse::FUNCTION_COMPLETE;
}
ServiceResponse abortAllCommands() {
for (auto cmd : commands) {
if (cmd->getState() != CommandState::COMPLETED) {
cmd->setCompletionStatus(CommandStatus::TASK_ABORTED, SenseData(0x0B, 0x00, 0x00, "Command aborted by ABORT TASK SET"));
}
}
std::cout << "[TaskSet] 任务集 " << itlNexusId << " 所有命令已中止" << std::endl;
return ServiceResponse::FUNCTION_COMPLETE;
}
void establishACA() {
isACAActive = true;
for (auto cmd : commands) {
if (cmd->getState() == CommandState::ENABLED && cmd->getTaskAttribute() != TaskAttribute::ACA) {
cmd->setState(CommandState::BLOCKED);
std::cout << "[TaskSet] 命令 " << cmd->getUniqueId() << " 因 ACA 进入阻塞状态" << std::endl;
}
}
std::cout << "[TaskSet] 任务集 " << itlNexusId << " ACA 条件已建立" << std::endl;
}
ServiceResponse clearACA() {
if (!isACAActive) return ServiceResponse::FUNCTION_COMPLETE;
isACAActive = false;
for (auto cmd : commands) {
if (cmd->getState() == CommandState::BLOCKED) {
cmd->setState(CommandState::ENABLED);
std::cout << "[TaskSet] 命令 " << cmd->getUniqueId() << " 因 ACA 清除进入启用状态" << std::endl;
}
}
std::cout << "[TaskSet] 任务集 " << itlNexusId << " ACA 条件已清除" << std::endl;
return ServiceResponse::FUNCTION_COMPLETE;
}
bool isACAEnabled() const { return isACAActive; }
std::string getITLNexusId() const { return itlNexusId; }
};
// -------------------------- SCSI 目标设备类(SAM-5 4.6.14) --------------------------
class ScsiTargetDevice : public IEventListener {
private:
std::string deviceName; // SCSI 设备名称(全球唯一)
std::map<std::string, LUN*> logicalUnits; // 逻辑单元(LUN 值 -> LUN 对象)
std::map<std::string, TaskSet*> taskSets; // 任务集(I_T_L Nexus ID -> 任务集)
std::vector<IEventListener*> eventListeners; // 事件监听器
uint32_t nextCommandId; // 下一个命令标识(自增)
uint32_t nextCRN; // 下一个命令参考号(I_T_L Nexus 内自增)
public:
ScsiTargetDevice(const std::string& name) : deviceName(name), nextCommandId(1), nextCRN(1) {
// 初始化默认逻辑单元(LUN 0,flat 寻址)
LUN* defaultLUN = new LUN(0, "flat");
logicalUnits[std::to_string(defaultLUN->getValue())] = defaultLUN;
std::cout << "[ScsiTargetDevice] 设备 " << deviceName << " 初始化,默认 LUN 0 已创建" << std::endl;
}
~ScsiTargetDevice() {
for (auto& lu : logicalUnits) delete lu.second;
for (auto& ts : taskSets) delete ts.second;
}
// 新增:获取逻辑单元(main.cpp 调用)
LUN* getLogicalUnit(uint64_t lunValue) {
auto iter = logicalUnits.find(std::to_string(lunValue));
return (iter != logicalUnits.end()) ? iter->second : nullptr;
}
// 新增:获取设备名称(ScsiInitiatorDevice 调用)
std::string getDeviceName() const {
return deviceName;
}
// 注册事件监听器
void registerEventListener(IEventListener* listener) {
eventListeners.push_back(listener);
}
void notifyEvent(ScsiEvent event, const Nexus& nexus)
{
std::cout << "[ScsiTargetDevice] 设备 " << "notifyEvent to be implmented"<< std::endl;
}
// 实现 IEventListener 的 onEvent 纯虚函数(关键修复)
void onEvent(ScsiEvent event, const Nexus& nexus) override {
std::cout << "[ScsiTargetDevice] 设备 " << deviceName << " 触发事件:";
switch (event) {
case ScsiEvent::POWER_ON: std::cout << "POWER_ON"; break;
case ScsiEvent::HARD_RESET: std::cout << "HARD_RESET"; break;
case ScsiEvent::LOGICAL_UNIT_RESET: std::cout << "LOGICAL_UNIT_RESET"; break;
case ScsiEvent::I_T_NEXUS_LOSS: std::cout << "I_T_NEXUS_LOSS"; break;
case ScsiEvent::POWER_LOSS_EXPECTED: std::cout << "POWER_LOSS_EXPECTED"; break;
}
std::cout << "(Nexus: " << nexus.getUniqueId() << ")" << std::endl;
// 通知所有监听器
for (auto listener : eventListeners) {
listener->onEvent(event, nexus);
}
// 事件处理:硬重置 -> 中止所有任务集命令
if (event == ScsiEvent::HARD_RESET) {
for (auto& ts : taskSets) {
ts.second->abortAllCommands();
}
}
}
// 执行命令(SAM-5 5.1)
ServiceResponse executeCommand(const Nexus& itlNexus, const CDB& cdb, TaskAttribute ta, SenseData& outSenseData) {
// 1. 验证 LUN 有效性
if (!itlNexus.lun || !itlNexus.lun->isValid()) {
outSenseData = SenseData(0x05, 0x25, 0x00, "Logical unit not supported");
return ServiceResponse::COMMAND_COMPLETE;
}
// 2. 获取或创建任务集(I_T_L Nexus 唯一)
std::string itlNexusId = itlNexus.getUniqueId();
if (taskSets.find(itlNexusId) == taskSets.end()) {
taskSets[itlNexusId] = new TaskSet(itlNexusId);
std::cout << "[ScsiTargetDevice] 为 Nexus " << itlNexusId << " 创建新任务集" << std::endl;
}
TaskSet* taskSet = taskSets[itlNexusId];
// 3. 创建 I_T_L_Q Nexus(含命令标识)
Nexus itlqNexus(itlNexus.initiatorPortId, itlNexus.targetPortId, itlNexus.lun, nextCommandId++);
// 4. 创建命令(CRN 自增)
Command* cmd = new Command(itlqNexus, cdb, ta, nextCRN++);
if (nextCRN > 0xFF) nextCRN = 1; // CRN 最大 0xFF,循环使用
// 5. 检查任务集是否满或 ACA 生效
if (taskSet->findCommand(cmd->getUniqueId()) != nullptr || (taskSet->isACAEnabled() && ta != TaskAttribute::ACA)) {
outSenseData = SenseData(0x05, 0x04, 0x00, "Task set full");
delete cmd;
return ServiceResponse::COMMAND_COMPLETE;
}
// 6. 添加命令到任务集
taskSet->addCommand(cmd);
// 7. 模拟命令执行
switch (cdb.operationCode) {
case 0x08: // READ 命令
std::cout << "[ScsiTargetDevice] 执行 READ 命令,LUN: " << itlNexus.lun->getValue() << std::endl;
if (cmd->needEstablishACA()) {
taskSet->establishACA();
outSenseData = SenseData(0x02, 0x00, 0x00, "ACA established after command completion");
cmd->setCompletionStatus(CommandStatus::CHECK_CONDITION, outSenseData);
} else {
cmd->setCompletionStatus(CommandStatus::GOOD, SenseData());
}
break;
case 0x0A: // WRITE 命令
std::cout << "[ScsiTargetDevice] 执行 WRITE 命令,LUN: " << itlNexus.lun->getValue() << std::endl;
cmd->setCompletionStatus(CommandStatus::GOOD, SenseData());
break;
default: // 未知命令
outSenseData = SenseData(0x05, 0x20, 0x00, "Invalid command operation code");
cmd->setCompletionStatus(CommandStatus::CHECK_CONDITION, outSenseData);
break;
}
return ServiceResponse::COMMAND_COMPLETE;
}
// 任务管理功能:中止指定命令(SAM-5 7.2)
ServiceResponse abortTask(const Nexus& itlqNexus) {
if (!itlqNexus.isITLQ()) return ServiceResponse::FUNCTION_REJECTED;
// 提取 I_T_L Nexus ID(去掉命令 ID 部分)
std::string itlqId = itlqNexus.getUniqueId();
size_t lastDashPos = itlqId.rfind("-");
if (lastDashPos == std::string::npos) return ServiceResponse::FUNCTION_REJECTED;
std::string itlNexusId = itlqId.substr(0, lastDashPos);
auto tsIter = taskSets.find(itlNexusId);
if (tsIter == taskSets.end()) return ServiceResponse::FUNCTION_COMPLETE;
return tsIter->second->abortCommand(itlqId);
}
// 任务管理功能:清除 ACA(SAM-5 7.4)
ServiceResponse clearACA(const Nexus& itlNexus) {
std::string itlNexusId = itlNexus.getUniqueId();
auto tsIter = taskSets.find(itlNexusId);
if (tsIter == taskSets.end()) return ServiceResponse::FUNCTION_REJECTED;
return tsIter->second->clearACA();
}
// 任务管理功能:逻辑单元重置(SAM-5 7.7)
ServiceResponse logicalUnitReset(const Nexus& itlNexus) {
notifyEvent(ScsiEvent::LOGICAL_UNIT_RESET, itlNexus);
std::string itlNexusId = itlNexus.getUniqueId();
auto tsIter = taskSets.find(itlNexusId);
if (tsIter != taskSets.end()) {
tsIter->second->abortAllCommands();
}
return ServiceResponse::FUNCTION_COMPLETE;
}
};
// -------------------------- SCSI 发起方设备类(SAM-5 4.6.9) --------------------------
class ScsiInitiatorDevice : public IEventListener {
private:
std::string deviceName; // 发起方设备名称
std::string initiatorPortId; // 发起方端口标识
ScsiTargetDevice* targetDevice; // 关联的目标设备
public:
ScsiInitiatorDevice(const std::string& name, const std::string& portId)
: deviceName(name), initiatorPortId(portId), targetDevice(nullptr) {}
// 关联目标设备
void attachTargetDevice(ScsiTargetDevice* target) {
targetDevice = target;
target->registerEventListener(this);
std::cout << "[ScsiInitiatorDevice] 发起方 " << deviceName << " 已关联目标设备 " << target->getDeviceName() << std::endl;
}
// 发送命令到目标设备
void sendCommand(const std::string& targetPortId, LUN* lun, const CDB& cdb, TaskAttribute ta) {
if (!targetDevice) {
std::cout << "[ScsiInitiatorDevice] 未关联目标设备,无法发送命令" << std::endl;
return;
}
Nexus itlNexus(initiatorPortId, targetPortId, lun);
SenseData senseData;
ServiceResponse resp = targetDevice->executeCommand(itlNexus, cdb, ta, senseData);
std::cout << "[ScsiInitiatorDevice] 命令发送完成,服务响应: ";
switch (resp) {
case ServiceResponse::COMMAND_COMPLETE:
std::cout << "COMMAND_COMPLETE";
if (senseData.senseKey != 0) {
std::cout << ",Sense Data: " << senseData.description;
}
break;
case ServiceResponse::SERVICE_DELIVERY_OR_TARGET_FAILURE:
std::cout << "SERVICE_DELIVERY_OR_TARGET_FAILURE";
break;
default:
std::cout << "未知响应";
break;
}
std::cout << std::endl;
}
// 发送任务管理请求:中止命令
void sendAbortTaskRequest(const std::string& targetPortId, LUN* lun, uint32_t commandId) {
if (!targetDevice) {
std::cout << "[ScsiInitiatorDevice] 未关联目标设备,无法发送中止请求" << std::endl;
return;
}
Nexus itlqNexus(initiatorPortId, targetPortId, lun, commandId);
ServiceResponse resp = targetDevice->abortTask(itlqNexus);
std::cout << "[ScsiInitiatorDevice] 中止命令请求完成,服务响应: " <<
(resp == ServiceResponse::FUNCTION_COMPLETE ? "FUNCTION_COMPLETE" : "FUNCTION_REJECTED") << std::endl;
}
// 接收目标设备事件通知
void onEvent(ScsiEvent event, const Nexus& nexus) override {
std::cout << "[ScsiInitiatorDevice] 发起方 " << deviceName << " 收到事件通知:";
switch (event) {
case ScsiEvent::LOGICAL_UNIT_RESET:
std::cout << "逻辑单元重置,Nexus: " << nexus.getUniqueId();
break;
case ScsiEvent::I_T_NEXUS_LOSS:
std::cout << "I_T Nexus 丢失,Nexus: " << nexus.getUniqueId();
break;
default:
std::cout << "其他事件";
break;
}
std::cout << std::endl;
}
};
2. 源文件(SAM5_Demo.cpp)
#include "SAM5_Core.h"
int main() {
setlocale(LC_ALL, ".UTF-8");
// -------------------------- 1. 初始化设备 --------------------------
ScsiTargetDevice targetDevice("TargetDisk01");
ScsiInitiatorDevice initiatorDevice("InitiatorHost01", "InitPort001");
initiatorDevice.attachTargetDevice(&targetDevice);
// 获取默认 LUN(LUN 0)
LUN* defaultLUN = targetDevice.getLogicalUnit(0);
if (!defaultLUN) {
std::cerr << "默认 LUN 0 不存在,程序退出" << std::endl;
return -1;
}
// -------------------------- 2. 场景1:发送 READ 命令(建立 ACA) --------------------------
std::cout << "\n===== 场景1:发送 READ 命令(NACA=1,建立 ACA) =====" << std::endl;
CDB readCDB;
readCDB.operationCode = 0x08; // READ 命令操作码
readCDB.controlByte = 0x02; // NACA 位=1(建立 ACA)
readCDB.parameters = {0x00, 0x00, 0x01};// 参数:读取 1 个块
initiatorDevice.sendCommand("TargetPort001", defaultLUN, readCDB, TaskAttribute::SIMPLE);
// -------------------------- 3. 场景2:发送 WRITE 命令(ACA 生效,命令阻塞) --------------------------
std::cout << "\n===== 场景2:发送 WRITE 命令(ACA 生效,非 ACA 属性命令被阻塞) =====" << std::endl;
CDB writeCDB;
writeCDB.operationCode = 0x0A; // WRITE 命令操作码
writeCDB.controlByte = 0x00; // NACA 位=0
writeCDB.parameters = {0x00, 0x00, 0x01};// 参数:写入 1 个块
initiatorDevice.sendCommand("TargetPort001", defaultLUN, writeCDB, TaskAttribute::SIMPLE);
// -------------------------- 4. 场景3:发送 ACA 属性命令(可执行) --------------------------
std::cout << "\n===== 场景3:发送 ACA 属性命令(ACA 生效时可执行) =====" << std::endl;
CDB acaCDB;
acaCDB.operationCode = 0x08; // READ 命令(ACA 属性)
acaCDB.controlByte = 0x00; // NACA 位=0
acaCDB.parameters = {0x00, 0x00, 0x01};// 参数:读取 1 个块
initiatorDevice.sendCommand("TargetPort001", defaultLUN, acaCDB, TaskAttribute::ACA);
// -------------------------- 5. 场景4:执行 CLEAR ACA 任务管理功能 --------------------------
std::cout << "\n===== 场景4:执行 CLEAR ACA 任务管理功能 =====" << std::endl;
Nexus itlNexus("InitPort001", "TargetPort001", defaultLUN);
ServiceResponse clearResp = targetDevice.clearACA(itlNexus);
std::cout << "CLEAR ACA 响应: " << (clearResp == ServiceResponse::FUNCTION_COMPLETE ? "FUNCTION_COMPLETE" : "FUNCTION_REJECTED") << std::endl;
// -------------------------- 6. 场景5:执行 LOGICAL UNIT RESET 任务管理功能 --------------------------
std::cout << "\n===== 场景5:执行 LOGICAL UNIT RESET 任务管理功能 =====" << std::endl;
ServiceResponse resetResp = targetDevice.logicalUnitReset(itlNexus);
std::cout << "LOGICAL UNIT RESET 响应: " << (resetResp == ServiceResponse::FUNCTION_COMPLETE ? "FUNCTION_COMPLETE" : "FUNCTION_REJECTED") << std::endl;
// -------------------------- 7. 场景6:发送 ABORT TASK 请求(中止命令 ID=3) --------------------------
std::cout << "\n===== 场景6:发送 ABORT TASK 请求(中止命令 ID=3) =====" << std::endl;
initiatorDevice.sendAbortTaskRequest("TargetPort001", defaultLUN, 3);
std::cout << "\n===== 所有场景执行完成 =====" << std::endl;
return 0;
}
3. 代码说明
(1)核心模块映射
| SAM-5 核心模块 | 代码对应组件 | 功能说明 |
|---|---|---|
| 架构模型 | ScsiTargetDevice/ScsiInitiatorDevice(设备)、LUN(逻辑单元)、Nexus(关系) | 模拟 SCSI 设备、逻辑单元与端口关系,实现设备间关联 |
| 命令模型 | Command(命令)、CDB(命令描述块)、SenseData(错误信息) | 封装命令执行流程,支持命令状态(NEW/DORMANT/ENABLED 等)与状态码(GOOD/CHECK_CONDITION 等) |
| 事件与通知模型 | IEventListener(监听器接口)、ScsiEvent(事件类型) | 实现事件触发与通知机制,支持电源开启、硬重置等事件处理 |
| 任务管理功能 | ScsiTargetDevice::abortTask/clearACA/logicalUnitReset | 实现 ABORT TASK、CLEAR ACA、LOGICAL UNIT RESET 等核心任务管理功能 |
| 任务集管理 | TaskSet(任务集) | 管理命令生命周期,处理 ACA 建立 / 清除、命令阻塞 / 启用等逻辑 |
(2)关键功能模拟
- ACA 机制:通过
TaskSet::establishACA()和clearACA()模拟 ACA 建立(阻塞非 ACA 命令)与清除(恢复命令执行); - 命令状态流转:命令创建时根据任务属性设置初始状态(SIMPLE→DORMANT、HEAD_OF_QUEUE→ENABLED),ACA 生效时转为 BLOCKED;
- 事件通知:目标设备触发事件(如逻辑单元重置)后,通过
notifyEvent()通知所有注册的监听器(如发起方设备); - 任务管理:支持中止指定命令、清除 ACA、逻辑单元重置等操作,符合 SAM-5 7.x 章节规范。
(3)编译与运行
- 依赖:C++11 及以上标准(支持 STL 容器与智能指针);
- 编译命令:
g++ SAM5_Demo.cpp -o SAM5_Demo -std=c++11; - 运行输出:将依次执行 6 个场景,打印命令执行、事件触发、任务管理操作的详细日志,展示 SAM-5 核心模型的交互流程。
4. 扩展建议
- 完善传输协议支持:当前 Demo 未涉及具体传输协议(如 FCP-4、iSCSI),可扩展
ScsiTransport类封装传输层服务(如 Send SCSI Command、Task Management Request); - 增加错误处理细节:扩展
SenseData以支持更多 SAM-5 定义的错误码(如附加错误码 0x29 表示 I_T NEXUS LOSS); - 多任务集并发:当前任务集与 I_T_L Nexus 一一对应,可扩展支持多 I_T Nexus 并发管理;
- 单元测试:基于 Google Test 等框架,为命令执行、任务管理等核心功能编写单元测试,验证是否符合 SAM-5 规范。

908

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



