Wow thanks for all that info Jim. The reason I considered Mach RPC in the first place was that most of the work I wanted to do in my kext was in the Mach part of the kernel. This meant that I had to use Mach search paths and all the appropriate Mach defines to make sure the macros and data structures in the headers were the same in my code as they are in the running kernel. Including BSD headers was pretty much impossible. I realised that I was going to have to put in some BSD code, so I made a separate target in my project to build a BSD library that is then linked in to the kext. That target uses the Kernel.framework search paths like most regular kext targets. Once I had the BSD target, it made sense to take the path of least resistance and publish a sysctl interface. I'm now passing a structure in to the kext via a sysctlbyname call, then doing a copyout of all my data to a user-specified address in the structure. So I've dumped my MIG code for now, but it's good to know it's possible for future reference! Sam On 21/05/2004, at 6:45 AM, Jim Magee wrote: On May 18, 2004, at 9:38 PM, Sam Vaughan wrote: What's not clear to me is how my kext would register the RPC services it provides with the part of the kernel that accepts the calls from user space. There are two methods in which Mach IPC/RPC operates in the kernel. The first method, I'll call it the "active listener method," behaves much like user-state Mach IPC. A kernel thread can wait on a Mach port for a message to arrive, handle it, and reply with a reply message. This method isn't used much in today's kernel (the ux_exception handler thread in BSD behaves this way). The disadvantage of this method is that it requires a thread switch between client and server. But the advantages are that port rights and memory are managed just like at user-space, and it requires "no hookup" into the kernel's IPC object dispatch mechanism. The second method, I'll call it the "passive invocation method," hooks into the middle the Mach IPC implementation for faster (but less "cooked") invocation. Under this method, the Mach IPC implementation determines that the destination is an "IPC kernel object." breaks off its processing of the message just after the "copyin" phase, and invokes the server in the context of the calling thread. As I said, the primary advantage of this method is speed. Only half of a typical IPC operation has been performed (there was a send, but no receive). But for many, the passive nature (tying up and using the user thread to invoke the kernel server) of the call is also an advantage. The disadvantages include having to deal with an "uncooked (e.g. un-received) message. The out-of-line memory is stored in short-hand form (and must be manually "copied-in" to the kernel before you can look at it). The port rights contained in the message are "naked" (i.e. there is no port name, with a set of associated, but managed, rights). Instead, you get a raw pointer to the port and you must manage any rights associated with those ports implicitly. But the biggest disadvantage from your question's perspective is that you must get the port defined as an "IPC kernel object" in the first place. You must "hook it up." There is no mechanism in place for random kernel extensions to "hook up" new IPC kernel objects (they are statically referenced in xnu/osfmk/kern/ipc_kobject.c). So, you must leverage one of the existing IPC kernel objects, or you must use the active listener model. The extensible IPC kernel objects are the IOKit io_connect() and io_service() objects. IOKit provides methods for exporting services using these. But short of using IOKit, there is no way to hook up a "passive" Mach port in a KEXT. That being said - how do you export a port to user-space? Again, IOKit provides a mechanism for doing this (the registry). Also, what port should the user space code use when it issues the RPC? The Kernel Programming doc says to look in bootstrap.h, but this file is empty in Darwin 7.3.0. What they should have said (I haven't looked it up to be sure), is to look in <servers/bootstrap.h>. But these services aren't available IN the kernel, only outside. Can anyone point me to some sample code that uses Mach RPC to cross the user-kernel boundary? The examples in Darwin such as upl_commit_range() and friends simply call Mach from BSD, which isn't really relevant to the issues I'm seeing. Actually, upl_commit_range() is defined in <mach/upl.h> and is published to user-space - although currently unused as a kernel-user boundary interface (until the EMMI gets re-published to user-space, there's not much use for a UPL out there). --Jim _______________________________________________ darwin-kernel mailing list | darwin-kernel@lists.apple.com Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/darwin-kernel Do not post admin requests to the list. They will be ignored.