Almost every operating system has a mechanism to start processes at system startup time that provide services not tied to an interactive user. In Windows, such processes are called services or Windows services. Windows services consist of three components: a service application, a service control program (SCP), and the service control manager (SCM).
Service applications, such as Web servers, consist of at least one executable that runs as a Windows service. Service applications are simply Windows executables (GUI or console, most without an interface) with additional code to receive commands from the SCM as well as to communicate the application's status back to the SCM. A user wanting to start, stop, or configure a service uses an SCP.
When you install an application that includes a service, the application's setup program must register the service with the system. A service configuration program uses the CreateService function to install a service in a SCM database. Here is an example of how to install a service:
#include <windows.h> #include <stdio.h> BOOL CreateSampleService() { TCHAR szPath[MAX_PATH]; if( !GetModuleFileName( NULL, szPath, MAX_PATH ) ) { printf("GetModuleFileName failed (%d)\n", GetLastError()); return FALSE; } schService = CreateService( schSCManager, // SCManager database TEXT("Sample_Srv"), // name of service lpszDisplayName, // service name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_DEMAND_START, // start type SERVICE_ERROR_NORMAL, // error control type szPath, // path to service's binary NULL, // no load ordering group NULL, // no tag identifier NULL, // no dependencies NULL, // LocalSystem account NULL); // no password if (schService == NULL) { printf("CreateService failed (%d)\n", GetLastError()); return FALSE; } else { CloseServiceHandle(schService); return TRUE; } }
When a setup program registers a service by calling CreateService, a message is sent to the SCM on the machine where the service will reside. The SCM then creates a registry key for the service under HKLM\SYSTEM\CurrentControlSet\Services. The Services key is the nonvolatile representation of the SCM's database.
Because most services don't have a user interface, they are built as console programs. The entry point of a console application is its main function. When the SCM starts a service program, it waits for it to call the StartServiceCtrlDispatcher function. So the main function of a service program calls the StartServiceCtrlDispatcher function to connect to the SCM and start the control dispatcher thread. StartServiceCtrlDispatcher accepts a list of entry points into services, one entry point for each service in the process. Each entry point is identified by the name of the service the entry point corresponds to. The dispatcher thread loops, waiting for incoming control requests for the services specified in the dispatch table. Here is an example of Writing a Service Program's main Function.
The SCM sends a service-start command each time it starts a service the process owns. For each start command it receives, the StartServiceCtrlDispatcher function creates a thread, called a service thread, to invoke the starting service's entry point and implement the command loop for the service. StartServiceCtrlDispatcher waits indefinitely for commands from the SCM and returns control to the process's main function only when all the process's services have stopped, allowing the service process to clean up resources before exiting.
A service entry point's first action is to call the RegisterServiceCtrlHandler function. This function receives and stores a pointer to a function, called the control handler, which the service implements to handle various commands it receives from the SCM. RegisterServiceCtrlHandler doesn't communicate with the SCM, but it stores the function in local process memory for the StartServiceCtrlDispatcher function. The service entry point continues initializing the service, which can include allocating memory, creating communications end points, and reading private configuration data from the registry. A convention most services follow is to store their parameters under a subkey of their service registry key, named Parameters. While the entry point is initializing the service, it might periodically send status messages, using the SetServiceStatus function, to the SCM indicating how the service's startup is progressing. After the entry point finishes initialization, a service thread usually sits in a loop waiting for requests from client applications. For example, a Web server would initialize a TCP listen socket and wait for inbound HTTP connection requests.
A service process's main thread, which executes in the StartServiceCtrlDispatcher function, receives SCM commands directed at services in the process and invokes the target service's control handler function (stored by RegisterServiceCtrlHandler). SCM commands include stop, pause, resume, interrogate, and shutdown, or application-defined commands.
This figure shows the internal organization of a service process. Pictured are the two threads that make up a process hosting one service: the main thread and the service thread.
The following is a simplified overview of what happens when a typical service is started by the service control manager:
By default Windows services are run under the virtual user "LocalService" that has administrative rights on the system. When a service runs as LocalService, Windows allows the user to configure it so it is "allowed to interact with desktop" (that is, display user-visible dialog boxes and other windows). However, if running as any other user, this option is not available.
Service Changes for Windows Vista
There have been significant changes to the services model to improve performance, reliability, security, management, and administration of services. These changes include:
References: