在内核控制ctl_enqueuedata调用中标识EINVAL

时间:2012-08-08 22:43:16

标签: macos kernel kernel-module kernel-extension

我想使用内核控件将内核扩展中的消息发送到用户程序。调用EINVAL时,我遇到ctl_enqueuedata错误。


我已经设置了内核控件,我正在尝试使用ctl_enqueuedata通过它发送消息。我正在设置

ep_ctl.ctl_flags = 0

在传递给ctl_register之前,the documents建议,应该导致ctl_unit自动设置。

引用kern_control.h

  

对于动态分配的控件ID,请勿设置CTL_FLAG_REG_ID_UNIT标志。

static struct kern_ctl_reg ep_ctl;
static kern_ctl_ref kctlref;

...

errno_t error;
bzero(&ep_ctl, sizeof(ep_ctl));  // sets ctl_unit to 0
ep_ctl.ctl_id = 0;
ep_ctl.ctl_unit = 0;
strncpy(ep_ctl.ctl_name, CONTROL_NAME, strlen(CONTROL_NAME));
ep_ctl.ctl_flags = 0x0; // not CTL_FLAG_REG_ID_UNIT so unit gets supplied. Not CTL_FLAG_PRIVILEGED either.
ep_ctl.ctl_send = EPHandleSend;
ep_ctl.ctl_getopt = EPHandleGet;
ep_ctl.ctl_setopt = EPHandleSet;
ep_ctl.ctl_connect = EPHandleConnect;
ep_ctl.ctl_disconnect = EPHandleDisconnect;
error = ctl_register(&ep_ctl, &kctlref);

printf("setupControl %d\n", error);

当我致电ctl_register时,它会返回0确定。

当我致电ctl_enqueuedata时,传入我的struct kern_ctl_reg我得到22,即EINVAL。其中一个论点似乎是不正确的。我传递的其他参数是静态测试字符串及其数据长度和零标记。

int result = ctl_enqueuedata(kctlref, ep_ctl.ctl_unit, filename, length, 0x0);

ep_ctl的{​​{1}}的值为.ctl_unit0的值为.ctl_id。可能是传递给6的{​​{1}}值无效/未初始化了吗?

ctl_unit说ctl_unit:

  

对于动态分配的控件ID

,将忽略此字段

这表明它无论如何都不是必需的?

我在初始化ep_ctl时遗漏了什么吗?

2 个答案:

答案 0 :(得分:1)

我认为你提供的错误值是ctl_enqueuedata()的第二个参数。您必须记住ep_ctl.ctl_unit回调中的struct sockaddr_ctl::sc_unit而不是EPHandleConnect(),而这应该是您应该传递到ctl_enqueuedata()的内容。

答案 1 :(得分:0)

我建议使用OSX的内核调试工具来弄清楚这里发生了什么。这将让您浏览相关的内核代码,并告诉您拒绝输入的位置。