One of the comments I made when doing my “first impressions” of the Mirra backup device was that the Windows software starts two separate services running in two different processes.
I see this a lot – people architect their product into multiple services (which is often a good thing), but they then run the services in separate processes.
Sometimes this is a good thing – for example, the Windows Media Connect add-on for Windows runs as two services – one service does very little, but runs as LocalSystem (full privileges). The other service (which does most of the work) runs in a limited LocalService account. By running as two services, in two different privilege levels, the Windows Media Connect carefully limits which functionality has to run with elevated privileges. This is a good example of the principle of least privilege – isolate the parts of the functionality that need higher privileges and run them out-of-proc instead of running the entire service with elevated privileges.
But sometimes it doesn’t really make sense. Mirra is a good example, and there are others as well. These products have multiple Windows Services, which run in the same security context, but use separate processes.
Why is this a big deal? Well, unlike *nix, on Windows, a process is a relatively expensive entity. It takes a non trivial amount of time to launch a process, and each process consumes a fair amount of system resources (something like 1M of virtual memory, just for the various process structures (virtual address map, handle table, etc), IIRC). Each process running drains the system of resources that could be used for your application, so it’s important to reduce the number of system processes running. It always annoys me when I install some application and discover that it’s installed three or four processes that run all the time on my machine, especially when those functions could have been combined into a single process.
For services, this is especially annoying – the NT service controller has had support for shared services built-in since NT 3.1.
You can see shared services in action on any Windows machine. If you have the SDK tool tlist.exe, you can run “tlist -s” and see the services running in each process. On my machine, tlist shows (among other things):
1280 svchost.exe Svcs: AudioSrv,BITS,CryptSvc,Dhcp,dmserver,ERSvc,EventSystem,helpsvc,lanmanserver,lanmanworkstatio
In this example, svchost.exe is running 26 different services. Without shared services, each of these would be a separate process, thus consuming a huge chunk of resources. In fact, that’s the entire purpose of svchost – it provides a common hosting framework for Windows to use for shared services. svchost.exe is an internal-only facility, but the functionality on which it is based is available for everyone. To specify a service as being a shared service, all you need to do is to specify the dwServiceType as SERVICE_WIN32_SHARE_PROCESS when you call CreateService and the service controller will do “the right thing”.
You need to do a smidge more work – if you’re a shared service, then when you call StartServiceCtrlDispatcher, you need to specify all the services that will be running in your process, but that’s about it.
When you ask the service controller to start a share process service, the service controller first looks to see if that service is started. If it’s not, it looks at the running service control dispatchers to see if there’s a dispatcher running for the new service. If there is a dispatcher running for the service, then it uses that dispatcher to start the new service, if there isn’t, it launches the process that was specified in the lpBinaryPathName parameter to CreateService.
The bottom line is that if you’re responsible for more than one service (or your product contains more than one service), you should seriously consider combining them into a single process – it’s not that much extra effort, and the benefits can be huge.