Chapter 3A Flashcards
A process
is a program in execution, and the status of the current activity of a process is represented by
the program counter, as well as other registers.
A process is independent
if it does not share data with any other processes executing in the system
process is cooperating
if it can affect or be affected by the other processes executing in the system.
Clearly, any process that shares data with other processes is a cooperating process
As a process executes, it changes state
The state of a process is defined in part by the current activity of
that process
Types of processes:
- New. The process is being created.
- Running. Instructions are being executed.
- Waiting. The process is waiting for some event to occur (such as an I/O completion or reception of a
signal). - Ready. The process is waiting to be assigned to a processor.
- Terminated. The process has finished execution
Each process is represented in the operating system by a process control block (PCB)—also called a task
control block
. A PCB is shown in Figure 3.3. It contains many pieces of information associated with a
specific process, including these: * Process state. The state may be new, ready, running, waiting, halted,
and so on. * Program counter. The counter indicates the address of the next instruction to be executed for
this process.
*
- CPU registers.
The registers vary in number and type, depending on the computer architecture. They
include accumulators, index registers, stack pointers, and general-purpose registers, plus any
condition-code information. Along with the program counter, this state information must be saved when
an interrupt occurs, to allow the process to be continued correctly afterward when it is rescheduled to run.
- CPU-scheduling information
This information includes a process priority, pointers to scheduling
queues, and any other scheduling parameters. (Chapter 5 describes process scheduling.) *
Memory-management information
This information may include such items as the value of the base and
limit registers and the page tables, or the segment tables, depending on the memory system used by the
operating system (Chapter 9). *
- Accounting information.
This information includes the amount of CPU
and real time used, time limits, account numbers, job or process numbers, and so on.
- I/O status
information.
This information includes the list of I/O devices allocated to the process, a list of open files,
and so on.
Threads
The process model discussed so far has implied that a process is a program that performs a single
thread of execution. For example, when a process is running a word-processor program, a single thread of
instructions is being executed. This single thread of control allows the process to perform only one task at
a time. Thus, the user cannot simultaneously type in characters and run the spell checker. Most modern
operating systems have extended the process concept to allow a process to have multiple threads of
execution and thus to perform more than one task at a time. This feature is especially beneficial on
multicore systems, where multiple threads can run in parallel. A multithreaded word processor could, for
example, assign one thread to manage user input while another thread runs the spell checker. On systems
that support threads, the PCB is expanded to include information for each thread. Other changes
throughout the system are also needed to support threads.
The number of processes currently in memory is known as the degree of multiprogramming.
Balancing
the objectives of multiprogramming and time sharing also requires taking the general behavior of a
process into account. In general, most processes can be described as either I/O bound or CPU bound. An
I/O-bound process is one that spends more of its time doing I/O than it spends doing computations. A
CPU-bound process, in contrast, generates I/O requests infrequently, using more of its time doing
computations.
As processes enter the system, they are put into a ready queue, where they are ready and waiting to
execute on a CPU’s core
This queue is generally stored as a linked list; a ready-queue header contains
pointers to the first PCB in the list, and each PCB includes a pointer field that points to the next PCB in
the ready queue. The system also includes other queues. When a process is allocated a CPU core, it
executes for a while and eventually terminates, is interrupted, or waits for the occurrence of a particular
event, such as the completion of an I/O request. Suppose the process makes an I/O request to a device
such as a disk. Since devices run significantly slower than processors, the process will have to wait for the
I/O to become available. Processes that are waiting for a certain event to occur — such as completion of
I/O — are placed in a wait queue (Figure 3.4). A common representation of process scheduling is a
queueing diagram, such as that in Figure 3.5. Two types of queues are present: the ready queue and a set
of wait queues. The circles represent the resources that serve the queues, and the arrows indicate the flow
of processes in the system.
Once the process is allocated a CPU core and is executing, one of several events could occur:
- The process could issue an I/O request and then be placed in an I/O wait queue. * The process could
create a new child process and then be placed in a wait queue while it awaits the child’s termination. * The
process could be removed forcibly from the core, as a result of an interrupt or having its time slice expire,
and be put back in the ready queue. In the first two cases, the process eventually switches from the
waiting state to the ready state and is then put back in the ready queue. A process continues this cycle
until it terminates, at which time it is removed from all queues and has its PCB and resources deallocated.
Tree of processes
During the course of execution, a process may create several new processes. As
mentioned earlier, the creating process is called a parent process, and the new processes are called the
children of that process. Each of these new processes may in turn create other processes, forming a tree of
processes
PID -> Most operating systems (including UNIX, Linux, and Windows) identify processes according to a
unique process identifier (or pid), which is typically an integer number. The pid provides a unique value
for each process in the system, and it can be used as an index to access various attributes of a process
within the kernel.
In general, when a process creates a child process,
s, that child process will need certain resources (CPU
time, memory, files, I/O devices) to accomplish its task. A child process may be able to obtain its
resources directly from the operating system, or it may be constrained to a subset of the resources of the
parent process. The parent may have to partition its resources among its children, or it may be able to
share some resources (such as memory or files) among several of its children. Restricting a child process
to a subset of the parent’s resources prevents any process from overloading the system by creating too
many child processes.
When a process creates a new process, two possibilities for execution exist:
- The parent continues to execute concurrently with its children. 2. The parent waits until some or all of
its children have terminated.
There are also two address-space possibilities for the new process:
- The child process is a duplicate of the parent process (it has the same program and data as the parent).
- The child process has a new program loaded into it.
FORK() SYSTEM CALL
A new process is created by the fork() system call. The new process consists of
a copy of the address space of the original process. This mechanism allows the parent process to
communicate easily with its child process. Both processes (the parent and the child) continue execution at
the instruction after the fork(), with one difference: the return code for the fork() is zero for the new
(child) process, whereas the (nonzero) process identifier of the child is returned to the parent
EXEC() SYSTEM CALL
exec() system call to replace the process’s memory space with a new program.
The exec() system call loads a binary file into memory (destroying the memory image of the program
containing the exec() system call) and starts its execution. In this manner, the two processes are able to
communicate and then go their separate ways. The parent can then create more children; or, if it has
nothing else to do while the child runs, it can issue a wait() system call to move itself off the ready queue
until the termination of the child. Because the call to exec() overlays the process’s address space with a
new program, exec() does not return control unless an error occurs.
The parent waits for the child process
s to complete with the wait() system call. When the child process
completes (by either implicitly or explicitly invoking exit()), the parent process resumes from the call to
wait(), where it completes using the exit() system call.
Windows system calls
As an alternative example, we next consider process creation in Windows.
Processes are created in the Windows API using the CreateProcess() function, which is similar to fork() in
that a parent creates a new child process. However, whereas fork() has the child process inheriting the
address space of its parent, CreateProcess() requires loading a specified program into the address space of
the child process at process creation. Furthermore, whereas fork() is passed no parameters,
CreateProcess() expects no fewer than ten parameters. The C program shown in Figure 3.10 illustrates the
CreateProcess() function, which creates a child process that loads the application mspaint.exe. We opt for
many of the default values of the ten parameters passed to CreateProcess(). Readers interested in pursuing
the details of process creation and management in the Windows API are encouraged to consult the
bibliographical notes at the end of this chapter. The two parameters passed to the CreateProcess() function
are instances of the STARTUPINFO and PROCESS INFORMATION structures. STARTUPINFO
specifies many properties of the new process, such as window size and appearance and handles to
standard input and output files. The PROCESS INFORMATION structure contains a handle and the
identifiers to the newly created process and its thread. We invoke the ZeroMemory() function to allocate
memory for each of these structures before proceeding with CreateProcess(). The first two parameters
passed to CreateProcess() are the application name and command-line parameters. If the application name
is NULL (as it is in this case), the command-line parameter specifies the application to load.
Process Termination
A process terminates when it finishes executing its final statement and asks the
operating system to delete it by using the exit() system call. At that point, the process may return a status
value (typically an integer) to its waiting parent process (via the wait() system call). All the resources of
the process —including physical and virtual memory, open files, and I/O buffers—are deallocated and
reclaimed by the operating system. Termination can occur in other circumstances as well. A process can
cause the termination of another process via an appropriate system call (for example, TerminateProcess()
in Windows). Usually, such a system call can be invoked only by the parent of the process that is to be
terminated. Otherwise, a user— or a misbehaving application—could arbitrarily kill another user’s
processes. Note that a parent needs to know the identities of its children if it is to terminate them. Thus,
when one process creates a new process, the identity of the newly created process is passed to the parent.
A parent may terminate the execution of one of its children for a variety of reasons, such as these: * The
child has exceeded its usage of some of the resources that it has been allocated. (To determine whether
this has occurred, the parent must have a mechanism to inspect the state of its children.) * The task
assigned to the child is no longer required. * The parent is exiting, and the operating system does not
allow a child to continue if its parent terminates.
Cascading termination
is normally initiated by the operating system. To illustrate process execution and
termination, consider that, in Linux and UNIX systems, we can terminate a process by using the exit()
system call, providing an exit status as a parameter: /* exit with status 1 */ exit(
under normal termination -> exit(
will be called either directly (as shown above) or indirectly, as the C
run-time library (which is added to UNIX executable files) will include a call to exit() by default
wait() system call
> A parent process may wait for the termination of a child process by using the wait()
system call. The wait() system call is passed a parameter that allows the parent to obtain the exit status of
the child. This system call also returns the process identifier of the terminated child so that the parent can
tell which of its children has terminated: pid t pid; int status; pid = wait(&status); When a process
terminates, its resources are deallocated by the operating system. However, its entry in the process table
must remain there until the parent calls wait(), because the process table contains the process’s exit status.
Orphans -
Now consider what would happen if a parent did not invoke wait() and instead terminated,
thereby leaving its child processes as orphans. Traditional UNIX systems addressed this scenario by
assigning the init process as the new parent to orphan processes. (Recall from Section 3.3.1 that init
serves as the root of the process hierarchy in UNIX systems.) The init process periodically invokes wait(),
thereby allowing the exit status of any orphaned process to be collected and releasing the orphan’s process
identifier and process-table entry. Although most Linux systems have replaced init with systemd, the
latter process can still serve the same role, although Linux also allows processes other than systemd to
inherit orphan processes and manage their termination.
Android Process Hierarchy
- Foreground process—
The current process visible on the screen, representing the application the user is
currently interacting with *
- Visible process—
A process that is not directly visible on the foreground but
that is performing an activity that the foreground process is referring to (that is, a process performing an
activity whose status is displayed on the foreground process)
- Service process
—A process that is similar to a background process but is performing an activity that is
apparent to the user (such as streaming music)
- Background process—
—A process that may be performing
an activity but is not apparent to the user
- Empty process
A process that holds no active components
associated with any application
Context switch
As mentioned in Section 1.2.1, interrupts cause the operating system to change a CPU core from its
current task and to run a kernel routine. Such operations happen frequently on general-purpose systems.
When an interrupt occurs, the system needs to save the current context of the process running on the CPU
core so that it can restore that context when its processing is done, essentially suspending the process and
then resuming it. The context is represented in the PCB of the process. It includes the value of the CPU
registers, the process state (see Figure 3.2), and memory-management information. Generically, we
perform a state save of the current state of the CPU core, be it in kernel or user mode, and then a state
restore to resume operations. Switching the CPU core to another process requires performing a state save
of the current process and a state restore of a different process. This task is known as a context switch and
is illustrated in Figure 3.6. When a context switch occurs, the kernel saves the context of the old process
in its PCB and loads the saved context of the new process scheduled to run. Contextswitch time is pure
overhead, because the system does no useful work while switching. Switching speed varies from machine
to machine, depending on the
memory speed, the number of registers that must be copied, and the existence of special instructions (such
as a single instruction to load or store all registers). A typical speed is a several microseconds.
There are several reasons for providing an environment that allows process cooperation:
- Information sharing
g. Since several applications may be interested in the same piece of information (for
instance, copying and pasting), we must provide an environment to allow concurrent access to such
information.
- Computation speedup
. If we want a particular task to run faster, we must break it into subtasks, each of
which will be executing in parallel with the others. Notice that such a speedup can be achieved only if the
computer has multiple processing cores.
- Modularity.
We may want to construct the system in a modular fashion, dividing the system functions
into separate processes or threads, as we discussed in Chapter 2.
Cooperating processes require an interprocess communication (IPC)
mechanism that will allow them to
exchange data— that is, send data to and receive data from each other
Shared memory -
- In the shared-memory model, a region of memory that is shared by the cooperating
processes is established. Processes can then exchange information by reading and writing data to the
shared region. Shared memory can be faster than message passing, since message-passing systems are
typically implemented using system calls and thus require the more time-consuming task of kernel
intervention. In shared-memory systems, system calls are required only to establish shared memory
regions. Once shared memory is established, all accesses are treated as routine memory accesses, and no
assistance from the kernel is required.
Message-passing model
communication takes place by means of messages exchanged between the
cooperating processes.Message passing is useful for exchanging smaller amounts of data, because no
conflicts need be avoided. Message passing is also easier to implement in a distributed system than shared
memory.
Interprocess communication using shared memory requires communicating processes to establish a region
of shared memory
Typically, a shared-memory region resides in the address space of the process creating
the shared-memory segment. Other processes that wish to communicate using this shared-memory
segment must attach it to their address space. Recall that, normally, the operating system tries to prevent
one process from accessing another process’s memory. Shared memory requires that two or more
processes agree to remove this restriction. They can then exchange information by reading and writing
data in the shared areas. The form of the data and the location are determined by these processes and are
not under the operating system’s control. The processes are also responsible for ensuring that they are not
writing to the same location simultaneously