Godfrey van der Linden writes:
I have done a little research on this issue and it isn't as easy as
I'd hoped. Their is currently no clean way of getting into launchd.
launchd is the replacement for our KUNC apis and it is more robust.
There are 3 main mechanisms to use.
1> mach_init: This is controlled through the /etc/mach_init.d and
mach_init_per_user.d directories. The general model is that
mach_init is configured with a set of 'named' ports that you can get
access to through the bootstrap name space. mach_init starts
listening on a port and if it finds a message it arranges for your
process to launch with the message still in its queue. As you can
see this is pretty cool, the problem is that you have to get the port
name into the kernel. The easiest way I can think of doing this is
to use the client daemon to do a io_async_method_scalarI_scalarO
which passes in a send right. There is a little bit of research that
has to be done about how you are going to keep a port reference once
the user client shutsdown.
2> inetd: Standard tricks here. Just so a so_send from inside a
kernel. I'm sure you are familar with this mechanism.
3> Dedicate a process to act as a helper for your driver using a
dedicated user client.
Thanks Godfrey,
I think I'll continue to use KUNCExecute() until a cleaner, easier,
and documented way to talk to launchd appears. If KUNCExecute()
disappears before then, I suppose the inetd route would be the best
way for me to go.
Would it help for me to file an enhancement request asking for a way
for an IOKit driver to signal launchd to start a program?
If Apple is trying to come up with a clean way to do this,
something like FreeBSD's devctl api would be really cool. Here's
how it works:
To get my user-level daemon started, I just install a devd.conf stanza
file in the correct place. This would be analagous to installing
a lauch item plist. The FreeBSD devd.conf stanza looks like this:
notify 0 {
match "system" "mx";
match "subsystem" "start_mapper";
action "/opt/mx/sbin/mx_start_mapper $notify";
};
And inside my driver, I call just this function:
int
mx_start_mapper(mx_instance_state_t *is)
{
char devname[16];
snprintf(devname, sizeof(devname), "mx%d", is->id);
devctl_notify("mx", "start_mapper", "dontcare", devname);
return 0;
}
Internally, the devctl_notify() call generates output on /dev/devctl,
which is read and parsed by devd, which matches it to existing rules
in stanzas like the above.
I'm sure it would be easy for somebody who knew something about both
Mach and launchd to add a mechanism like this to IOKit.
Cheers,
Drew