2.1. Components of a ProcessThe Solaris kernel supports an entity known as a process and maintains a systemwide process table, where each process is uniquely identified in the kernel by a positive integer called the process identification number, or PID. Solaris is a multiuser, multitasking operating system and as such supports the coexistence of many processes. On systems with sufficient hardware resources (processors, memory), several thousand processes may exist at any time and any number of them may have multiple threads of execution. 2.1.1. Thread ObjectsThreaded execution, both within the kernel at large and user processes, is integrated into the core of the Solaris kernel. Solaris is a multithreaded operating system; tasks performed by the operating system are executed as kernel threads. For multithreaded processes, there are user threads, which are created with a lightweight process (LWP)a kernel object that allows user threads to execute and enter the kernel independently of other threads in the same process. The unit of scheduling and execution in Solaris is the kernel thread; thus, user threads in processes must be linked to a kernel thread for execution. The relationship among these process objects is shown in Figure 2.1. Figure 2.1. Process Objects
The names of the process objects, along with a definition, and location of the structure definition in the OpenSolaris source code, are shown in Table 2.1.
Table 2.1 defines a process as a state container for threads. Process state refers to all the bits of information contained within a process that the kernel needs to effectively manage the process. From a process perspective, the kernel abstracts execution resourcesa virtual machine for executing instructions. These are uncontended resources from the process perspective, since processes exist unaware of other processes running within the same instance of the operating system. It's a function of the kernel to manage the underlying hardware resources (processors, physical memory, I/O channels) and to provide each process the resources it requires: execution time on processors and allocation of physical memory, as well as to perform privileged services, such as network and disk IO. The kernel can impose constraints on how much of a given resource a process can consume, and Solaris includes a sophisticated resource management framework for allocating specific quantities of available resources (for example, processor cycles) and imposing thresholds or limits on how much of a particular resource a process can consume (see Section 2.5.1). The kernel maintains a process structure (proc_t) for every process in the system; within a proc_t, process state data is maintained and referenced. proc_t itself resides in the kernel's address space, and as such is protected from access by user processes. Protection boundaries exist in the form of access modes and memory page-level protections such that user processes cannot directly read or write the kernel's address space, and the address space of user processes are protected from access by other processes in the system. Since the kernel exists as a layer of software between the hardware and user processes, direct access to hardware is protected and available to user processes only through a well-defined set of system services. These services are implemented as application programming interfaces (APIs) that can be called from user programs to have the kernel perform a privileged task on behalf of the calling process, such as read or write a file, issue a control command to a device, create a new process or thread, allocate memory for the process to use, etc. The set of APIs that exist directly between user processes and the kernel are collectively known as system calls, documented in section two of the man pages. Figure 2.2. System Calls
Process information and control is available to users through a set of commands that make use of the process file system, procfs. Procfs is a pseudo file system that abstracts process information and control as a set of files and directories, rooted at /proc (see Section 2.10). Commonly used commands, such as ps(1), prstat(1), and the per-process utilities described in the proc(1) man page, are built on /proc. As we move through this chapter, you'll see examples of these commands in action. Just as every process in the kernel has a unique PID, so the other objects that are part of the process model have an integer namespace; user threads and LWPs have an LWP_ID, and kernel threads have a thread ID (TID). The process model in Solaris 10 (which differs from previous releases) simplifies the namespace assignment. From a user-process perspective, the kernel thread ID is derived from the LWP_ID (when a new thread is created, the LWP is created before the kernel thread, but more on that in a bit). A full view of the process ID and LWP ID namespace can be observed with the ps(1) and prstat(1) commands. sol9$ prstat -Lc PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID 9 root 19M 15M sleep 59 0 6:29:58 1.2% svc.configd/12 9 root 19M 15M sleep 54 0 1:34:36 0.2% svc.configd/13 222 root 6608K 3144K sleep 44 0 13:20:22 0.2% inetd/1 286 root 7664K 4088K sleep 59 0 7:21:14 0.1% automountd/1 25092 root 8568K 4968K sleep 59 0 0:00:00 0.1% sshd/1 25245 mauroj 4992K 4576K cpu8 49 0 0:00:00 0.1% prstat/1 25295 allanp 1624K 1288K sleep 52 0 0:00:00 0.1% csh/1 25301 allanp 1528K 1168K cpu1 34 0 0:00:00 0.1% csh/1 25188 allanp 1640K 1304K sleep 59 0 0:00:00 0.0% csh/1 25287 root 4072K 2312K sleep 52 0 0:00:00 0.0% in.rshd/1 9 root 19M 15M sleep 59 0 1:01:20 0.0% svc.configd/7 25187 root 4072K 2312K sleep 59 0 0:00:00 0.0% in.rshd/1 25151 mauroj 8376K 2888K sleep 59 0 0:00:00 0.0% sshd/1 14906 allanp 9400K 2752K sleep 60 0 0:00:01 0.0% cp/1 23006 allanp 9400K 3936K sleep 60 0 0:00:00 0.0% cp/1 Total: 108 processes, 275 lwps, load averages: 0.52, 0.65, 0.90 The example above is the partial output of a prstat -Lc command and shows a small subset of the information maintained for all running processes. As we move through the chapter, we explore the fields displayed above, along with with tools and utilities available for observing and controlling processes. 2.1.2. Core Process ComponentsA process is represented internally in the kernel as a data structure, defined in usr/src/uts/common/sys/proc.h. We explore the various fields defined in the process structure in Section 2.4. Here, we provide a high-level view of the major components of a process in Solaris. These process components are shared by all the threads in a multithreaded process.
The items listed above offer a high-level description of the major components of a process in Solaris. An examination of usr/src/uts/common/sys/proc.h reveals a considerable number of proc_t structure members required to make it all work as well as it does. Many of these are will be examined more closely in subsequent sections. |