SCSIControllerDriverKit:UserCreateTargetForID进程阻塞问题排查求助
DriverKit迁移:Thunderbolt RAID驱动无法创建SCSI设备排查方案
问题背景
我们正在将Thunderbolt RAID存储设备的内核扩展(kext)驱动迁移至DriverKit框架。设备通过Thunderbolt连接后识别为PCI设备,原kext核心功能是为每个虚拟RAID阵列创建虚拟SCSI设备,使系统可将其作为常规磁盘使用。目前基于SCSIControllerDriverKit文档进行迁移,但遇到功能阻塞问题。
当前问题
调用UserCreateTargetForID()创建SCSI设备时,系统发送的第一条SCSI命令**Test Unit Ready(命令0)**已被设备接收并回复,但回复提交给系统后,进程陷入等待状态:
- 未触发后续SCSI命令(如kext日志中的INQUIRY命令18)
- 最终未完成虚拟SCSI设备的创建
对比日志
正常工作的kext日志
15:06:17.902539+0700 Target device try to create for idx:0 15:06:17.902704+0700 Send command 0 for target 0 len 0 15:06:18.161777+0700 Complete command: 0 for target: 0 Len: 0 status: 0 flags: 0 15:06:18.161884+0700 Send command 18 for target 0 len 6 15:06:18.161956+0700 Complete command: 18 for target: 0 Len: 6 status: 0 flags: 0 15:06:18.162010+0700 Send command 18 for target 0 len 44 15:06:18.172972+0700 Complete command: 18 for target: 0 Len: 44 status: 0 flags: 0 15:06:18.275501+0700 Send command 18 for target 0 len 36 15:06:18.275584+0700 Complete command: 18 for target: 0 Len: 36 status: 0 flags: 0 15:06:18.276257+0700 Target device created for idx:0
异常的dext日志
15:54:10.903466+0700 Try to create target for 0 UUID 432421434863538456 - CustomThread 15:54:10.903633+0700 UserDoesHBAPerformAutoSense - DefaultQueue 15:54:10.903763+0700 UserInitializeTargetForID - DefaultQueue 15:54:10.903876+0700 UserDoesHBASupportMultiPathing DefaultQueue 15:54:10.904200+0700 UserProcessParallelTask start - DefaultQueue 15:54:10.904298+0700 Sent command : 0 len 0 for target 0 - SendCommandCustomThread 15:54:11.163003+0700 Disable interrupts - InterruptQueue 15:54:11.163077+0700 Complete cmd : 0 for target: 0 len: 0 status: 0 flags: 0 - InterruptQueue 15:54:11.163085+0700 Enable interrupts - InterruptQueue
当前任务完成代码
SCSIUserParallelResponse osRsp = {0}; osRsp.fControllerTaskIdentifier = osTask->taskId; osRsp.fTargetID = osTask->targetId; osRsp.fServiceResponse = kSCSIServiceResponse_TASK_COMPLETE; osRsp.fCompletionStatus = (SCSITaskStatus) response->status; // Transfer length computation. osRsp.fBytesTransferred = transferLength; // === 0 for this case. ParallelTaskCompletion(osTask->action, osRsp); osTask->action->release();
排查与解决建议
1. 修正任务完成的队列上下文
DriverKit要求任务完成回调必须在驱动的默认队列上执行,不能直接在InterruptQueue或自定义线程调用ParallelTaskCompletion。跨队列调用可能导致系统内部同步死锁,修改方式:
// 获取驱动默认队列 OSQueue* defaultQueue = GetDefaultQueue(); // 提交任务完成操作到默认队列 defaultQueue->dispatch(^{ ParallelTaskCompletion(osTask->action, osRsp); osTask->action->release(); });
2. 校验SCSI响应结构的完整性
确保SCSIUserParallelResponse的所有必填字段都正确初始化:
- 确认
fCompletionStatus是kSCSITaskStatus_GOOD(对应status 0),避免类型转换错误 - 如果
UserDoesHBAPerformAutoSense返回true,即使Test Unit Ready成功,也要确保fSenseDataLength设为0,避免系统等待sense数据
3. 检查Target初始化逻辑
- 验证
UserInitializeTargetForID的返回值:是否正确设置了目标设备的属性(如支持的LUN数、SCSI协议版本) - 确认
UserDoesHBASupportMultiPathing的返回值是否符合设备实际情况,错误的返回可能导致系统跳过后续流程
4. 补充调试日志
- 在
ParallelTaskCompletion调用前后添加日志,确认回调是否被执行 - 开启系统DriverKit调试日志,查看底层错误:
log stream --predicate 'subsystem == "com.apple.DriverKit"' --debug
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

