Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos 在没有基础IOBlockStorageDevice的情况下发布IOMedia_Macos_Kernel_Iokit_Kernel Extension - Fatal编程技术网

Macos 在没有基础IOBlockStorageDevice的情况下发布IOMedia

Macos 在没有基础IOBlockStorageDevice的情况下发布IOMedia,macos,kernel,iokit,kernel-extension,Macos,Kernel,Iokit,Kernel Extension,简而言之,我的问题是: KEXT发布在其提供程序堆栈中没有IOBlockStorageDevice的IOMedia对象是否是一种可接受/常见的做法 背景: 我正在编写一个kext,它将为用户空间提供某种虚拟设备。 目前,我有一个与IOResources匹配的驱动程序,然后创建一个从IOMedia派生的类对象,并将其附加到“this”。发布此媒体对象后,标准IOMediaBSDClient将连接到该对象并在/dev/中创建一个节点 第一次测试顺利通过,我可以成功地打开创建的设备并从中读取数据,但当

简而言之,我的问题是:

KEXT发布在其提供程序堆栈中没有IOBlockStorageDevice的IOMedia对象是否是一种可接受/常见的做法

背景:

我正在编写一个kext,它将为用户空间提供某种虚拟设备。 目前,我有一个与IOResources匹配的驱动程序,然后创建一个从IOMedia派生的类对象,并将其附加到“this”。发布此媒体对象后,标准IOMediaBSDClient将连接到该对象并在/dev/中创建一个节点

第一次测试顺利通过,我可以成功地打开创建的设备并从中读取数据,但当我尝试使用本机FS驱动程序安装它时,我遇到了一个问题。设备成功挂载,挂载点可浏览,但在此之后不久,由于vfs代码内部的segfault,内核陷入恐慌

经过长时间的调试,我找到了问题的根源:

  • IOMediaBSDClient通过迭代媒体父级中的IOBlockStorageDevice对象,然后迭代这些设备提供的所有媒体对象,并将其BSD单元号组合到一个位掩码中,来实现DKIOCGETTHROTTLEMASK ioctl。由于我的媒体没有任何IOBlockStorageDevice父级,因此生成的掩码为0
  • vfs_init_io_attributes()使用此ioctl返回的值填充对应于我的装载的mp struct的mnt_throttle_mask字段
  • 紧接着,mnt_throttle_mask通过计算其中的尾随零点转换为mnt_devbsdunit。因为在我的例子中mnt_throttle_mask是0,所以mnt_devbsdunit变成64
  • mnt_devbsdunit被spec_strategy(以及其他一些处理节流的函数)用作_throttle_io_info中的元素号,它是LOWPRI_MAX_NUM_DEV元素的数组,LOWPRI_MAX_NUM_DEV等于64。 显然,访问_throttle_io_info的64个元素会破坏紧随其后的数据,在我的例子中,这就是speclish数组
  • 目前,我在代码中看到了两种解决方法: 1.实现从IOMediaBSDClient派生的类,该类将正确处理DKIOCGETTHROTTLEMASK ioctl。 2.重写代码以发布IOBlockStorageDevice对象,并让标准IOBlockStorageDriver发布媒体对象

    就我个人而言,我更喜欢第一种解决方案,但我遇到的问题似乎相当核心,我无法摆脱我正在做一些根本错误的事情的想法

    我希望将来避免出现类似的问题,因此我提出这个问题


    编辑:至少对于OSX10.8.3和10.8.5是这样。我还没有在其他版本上测试它。

    我可能会使用
    IOBlockStorageDevice
    子类。我用这种方式写过一些驱动程序,从未遇到过任何问题。直接IOSt/IOMIDA驱动程序对于“过滤器”驱动程序(逻辑卷管理、RAID、加密等)都很有用——任何位于“真正的”块设备上的东西),但正如您所发现的,OS的某些区域期望有“<代码> IOBLROSTSTAREDIGRIVE < /COD> >代码> IOBLROWSTORACED设备基金会。 从
    IOStorage
    转换到
    IOBlockStorageDevice
    非常简单:方法名称的前缀几乎都是“do”或“report”,在其他方面语义几乎完全相同。从长远来看,这可能会为你节省一些麻烦。不要自己创建IOBlockStorageDriver对象-只要您在
    IOBlockStorageDevice
    子类实例上调用
    registerService()
    ,匹配的I/O工具包就会为您创建它


    这里有一些例子,包括书中一个非常简单的例子——即使你没有这本书,你也可以得到示例代码——第14章。

    谢谢你的回答。我将代码转换为IOBlockStorageDevice子类,现在它运行良好。无论如何,这似乎是本例中的唯一选项,因为经过一些调查,我发现不能简单地在IOMediaBSDClient中重新实现DKIOCGETTHROTTLEMASK ioctl,因为它直接在dkioctl函数中处理。很高兴您已经解决了所有问题!我以前不知道DKIOCGETTHROTTLEMSASK的问题,你每天都能学到新东西。:-)