我目前正在使用IOKit开发虚拟SCSI设备驱动程序。我的驱动程序加载正常,我可以使用ExFat,FAT32或HFS +格式化我的设备。
我还可以使用带有任何这些文件系统的CLI将文件复制到我的虚拟设备或从我的虚拟设备复制文件。使用ExFat或FAT32,我也可以使用Finder从我的虚拟设备复制或查看文件,但是当驱动器格式化为HFS +(Journaled)时不能。
使用HFS +时,我得到与Finder,Spotlight或Preview相关的内核恐慌。例如,当系统在将文件复制到磁盘后尝试预览文件时,就会发生这种情况。这是来自内核恐慌的示例日志:
Mon Jun 30 22:47:51 2014
panic(cpu 4 caller 0xffffff8005dd1401): "cluster_read_copy: failed to get pagelist"@/SourceCache/xnu/xnu-2422.100.13/bsd/vfs/vfs_cluster.c:3732
Backtrace (CPU 4), Frame : Return Address
0xffffff80e9aa3810 : 0xffffff8005c22fa9
0xffffff80e9aa3890 : 0xffffff8005dd1401
0xffffff80e9aa3a30 : 0xffffff8005dd0a85
0xffffff80e9aa3cf0 : 0xffffff8005f6b876
0xffffff80e9aa3d80 : 0xffffff8005dfdd21
0xffffff80e9aa3e00 : 0xffffff8005df38d5
0xffffff80e9aa3e50 : 0xffffff8005ff1cfe
0xffffff80e9aa3ef0 : 0xffffff8005ff1e79
0xffffff80e9aa3f50 : 0xffffff8006040653
0xffffff80e9aa3fb0 : 0xffffff8005cf3c56
BSD process name corresponding to current thread: Finder
Boot args: debug=0x144
Mac OS version:
13D65
Kernel version:
Darwin Kernel Version 13.2.0: Thu Apr 17 23:03:13 PDT 2014; root:xnu-2422.100.13~1/RELEASE_X86_64
以下是上述恐慌日志的堆栈跟踪:
mach_kernel`panic + 201 at debug.c:353
mach_kernel`cluster_read_copy + 2001 at vfs_cluster.c:3732
mach_kernel`cluster_read_ext + 5045 at vfs_cluster.c:3441
mach_kernel`hfs_vnop_read + 566 at hfs_readwrite.c
mach_kernel`VNOP_READ + 225 at kpi_vfs.c:3247
mach_kernel`vn_read + 245 at vfs_vnops.c:939
mach_kernel`dofileread + 174 at sys_generic.c:377
mach_kernel`pread_nocancel + 137 at sys_generic.c:266
mach_kernel`unix_syscall64 + 499 at systemcalls.c:370
mach_kernel`hndl_unix_scall64 + 22
我很难确定问题,但正如上面暗示的那样已经缩小到HFS +。 HFS +有什么特别之处可能导致这种情况吗?
由于问题与VFS和分页(?)有关,我开始怀疑我是否正确处理了我的IOMemoryDescriptors(我相信我是基于我在Apple文档中读到的内容)。有人遇到类似问题吗?这通常表示特定类型的问题吗?
更新:我已经确认在HFS +中禁用日记功能不会对上述结果产生影响。
UPDATE2:恐慌日志每次都是一致的。只有在满足以下所有条件时才会发生恐慌:
当第一个文件完成复制到设备时,内核始终一直处于恐慌状态。可以复制许多等于或大于几MB的小文件而不会引起恐慌。我甚至可以使用终端将文件大文件(> 30 MB)复制到卷中,然后在Finder中读取/打开它们。
答案 0 :(得分:1)
kernel source表示恐慌是由于对ubc_create_upl()
的调用失败造成的。源for that function中的注释反过来表明返回模式如下:
* Returns: KERN_SUCCESS The requested upl has been created
* KERN_INVALID_ARGUMENT The bufsize argument is not an even
* multiple of the page size
* KERN_INVALID_ARGUMENT There is no ubc_info associated with
* the vnode, or there is no memory object
* control associated with the ubc_info
* memory_object_upl_request:KERN_INVALID_VALUE
* The supplied upl_flags argument is
* invalid
从反汇编和恐慌日志的寄存器内容(您未在问题中提供)中,可以确定实际的返回码。并不是说这似乎会有所帮助,因为你的代码还没有在这个特定的系统调用上被调用过;我强烈怀疑你是否会导致某些内核资源耗尽,这恰好是某种池完全干涸的地方。很可能是你说的内存描述符,因为这里创建的UPL将被包装在内存描述符中,然后传递给mount的块设备的IOKit后端。
您可以在加载驱动程序之前检查ioclasscount
和zprint
,然后再次定期转储它们的输出直到崩溃,然后将输出与正在运行的任何内容进行比较。同样好的想法是审核代码以匹配prepare()/complete()
和retain()/release()
调用,特别是在请求内存描述符上。
2机器调试也可能有所帮助;例如,您可以检查用于VNOP_READ
的vnode对应的文件。如果在甚至不在您设备的卷上的文件上发生任何崩溃,那么您几乎肯定会遇到一些资源耗尽或内存损坏。您将能够找到ubc_create_upl()
呼叫失败的确切原因。您还可以检测代码以收集数据,然后在调试器中进行检查。