This post is a continuation of the compulsive thoughts about OSX vs Windows kernel development started here: Part # 1
So, it’s being a while since I was writing about OSX. My project has grown up a little and it’s time to release a first alpha. The kernel extention (kext) behaves as a socket level and an IP filter level NKE which is doing a bunch of stuff related to networking and is a very very simular to the concepts of TDI and NDIS filters which do exist in Windows world.
If you are not familiar with TDI or NDIS this post might be not of any use for you, so you may just skip it. If you are, well … If you’ve been writing TDI filters you would know a few gotchas you have to follow in order to avoid any incompatibility problems with third party software. Since this post is more about OSX rather than Windows, I would not go too much into details on Windows. So, this is what makes development on Windows a hell:
1. Proper registration of your filter in PNP_TDI group 2. Handling special guys like Juniper VPN (NEO_FLT_xx_xx.sys) 3. Proper handling of not-sufficient IRP stack location count in your dispatch routine 4. Doing some tricks with Afd.sys IrpStackSize 5. Impossibility to dynamically unload TDI filter 6. Cross signing your code in order to load in x64 bit Windows 7. Remember verisign changing the key length recently ... ? 8. Messing up with difxapp in your msi code and catching ugly bugs with poor logs (but with very verbose output) 9. Setupping DTM & passing WHQL tests for each flavour of Windows 10. Shipping x32 / x64 binaries for TDI + NDIS IM filters separately 11. Spinlocks everywhere (remember: you might be called at DISPATCH_LEVEL IRQL)
Well, it already sounds complicated. In OSX world things are a way simpler:
1. Your socket level NKE or ip level NKE do not have to put themselfes into any groups. Just load it at any time using kextload 2. I did not (yet) encounter any incompatibility with VirualBox, VmWare, BitDefender. Maybe, later 3. There is no IRP concept in OSX world. You have mach ports, and it certainly looks simpler.NKE is using callbacks approach 4. Not applicable 5. You can unload your NKE kext in OSX, just make sure you unregister properly from appropriate protocol 6. You don't have to be signed to load kext. Just have to be root 7. Not applicable 8. You don't have any complex frameworks for installations of drivers. Load via sh script or do it autoload 9. No DTM or WHQL nightmares. I like DTM framework and I use it for my automated tests, but I dislike the idea of paying per each submission and overall complexity behind the process 10. OSX has fat binaries concept, i.e. a single executable file, which has two or more binaries inside which are automatically loaded on a needed architecture. Cool, huh? 11. You are free to use mutexes, semaphors, read write mutexes, etc
What actually strikes me is that it’s quite hard to get a RBT (red-black tree) (mostly known as std::map in STL) in Windows kernel: you are stuck with AVL or splay trees via RtlGenericTable routines, while in OSX you are free to use either RBT or Splay Tree just by using a few macroses. You have a rich set of synchronization primitives for your needs (interlocked routines, mutexes, semaphores, lock groups, read write mutexes, etc) and you are not stuck to spinlocks like in TDI filters.
Despite that, when it comes to packaging stuff: everything is extremely simpler: you just create a fat binary, so your driver will load in x32 or x64 or ppc just out of the box. No need to provide any special packages for those architectures. Just single, universal package.
I already mentioned that Xcode is used to write drivers, which is not yet the case for Windows 7 and Visual Studio (in 2012!!!). What I did not mention is the approach Xcode uses when doing automation of build scripts via command line: when you compile your project in command line, it just creates a single folder in your project tree called “build”. This folder contains two files: compiled binary and compiled binary symbols. That’s it. Now, compile your project in Visual Studio and check how many obj files and other crap has crowed the directory 😉
What I did not talked about is … handling crash dumps. According to Microsoft, in a bug check callback, the system is dead and it is not safe to use any file system so the dump is stored in page file and then get’s extracted during next startup. You don’t have out of the box support to send crash dumps to some local server so that you will be able to analyze it.
In OSX world you can just configure to send your kernel panic dump to a file server (can be a simple Mac machine, not necessarily a server: Mac Book Air, or MacMini, or iMac, etc). Now, what happens when it panics is that it sends the dump right away, even over wi-fi connection :). I think for Redmond guys this is a very big shame :). If you are reading this and not getting red, please read it again :). Surprisingly it works well even on slow connection over wi-fi. Another interesting thing is that after the dump is sent to server, you can do remote connection over gdb and analyze the situation.
I am starting to like OSX more & more: it gives you quite rich api and does not put you in a strict hell boundaries you have in Windows world.