This chapter extends the material presented in Chapters 24 to 27 by covering a variety of topics related to process creation and program execution. We describe process accounting, a kernel feature that writes an accounting record about each process on the system as it terminates. We then look at the Linux-specific clone() system call, which is the low-level API that is used to create threads on Linux. We follow this with some comparisons of the performance of fork(), vfork(), and clone(). We conclude with a summary of the effects of fork() and exec() on the attributes of a process.
28 Process Creation and Program Execution in More Detail
28.1 Process Accounting
28.2 The clone() System Call
28.2.1 The clone() flags Argument
28.2.2 Extensions to waitpid() for Cloned Children
28.3 Speed of Process Creation
28.4 Effect of exec() and fork() on Process Attributes
28.5 Summary
28.6 Exercises
2009-08-29
2009-08-28
Chapter 37 is in copyedit
Chapter 34 already came back from copyedit, and Chapters 35 and 36 also went to copyedit and came back already. Now Chapter 37 is in copyedit.
Chapter 27: Program Execution
This chapter follows from our discussion of process creation and termination in the previous chapters. We now look at how a process can use the execve() system call to replace the program that it is running by a completely new program. We then show how to implement the system() function, which allows its caller to execute an arbitrary shell command.
27 Program Execution
27.1 Executing a New Program: execve()
27.2 The exec() Library Functions
27.2.1 The PATH Environment Variable
27.2.2 Specifying Program Arguments As a List
27.2.3 Passing the Caller's Environment to the New Program
27.2.4 Executing a File Referred to by a Descriptor: fexecve()
27.3 Interpreter Scripts
27.4 File Descriptors and exec()
27.5 Signals and exec()
27.6 Executing a Shell Command: system()
27.7 Implementing system()
27.8 Summary
27.9 Exercises
27 Program Execution
27.1 Executing a New Program: execve()
27.2 The exec() Library Functions
27.2.1 The PATH Environment Variable
27.2.2 Specifying Program Arguments As a List
27.2.3 Passing the Caller's Environment to the New Program
27.2.4 Executing a File Referred to by a Descriptor: fexecve()
27.3 Interpreter Scripts
27.4 File Descriptors and exec()
27.5 Signals and exec()
27.6 Executing a Shell Command: system()
27.7 Implementing system()
27.8 Summary
27.9 Exercises
2009-08-27
Chapter 26: Monitoring Child Processes
In many application designs, a parent process needs to know when one of its child processes changes state--when the child terminates or is stopped by a signal. This chapter describes two techniques used in monitoring child processes: the wait() system call (and its variants) and the use of the SIGCHLD signal.
26 Monitoring Child Processes
26.1 Waiting on a Child Process
26.1.1 The wait() System Call
26.1.2 The waitpid() System Call
26.1.3 The Wait Status Value
26.1.4 Process Termination from a Signal Handler
26.1.5 The waitid() System Call
26.1.6 The wait3() and wait4() System Calls
26.2 Orphans and Zombies
26.3 The SIGCHLD Signal
26.3.1 Establishing a Handler for SIGCHLD
26.3.2 Delivery of SIGCHLD for Stopped Children
26.3.3 Ignoring Dead Child Processes
26.4 Summary
26.5 Exercises
26 Monitoring Child Processes
26.1 Waiting on a Child Process
26.1.1 The wait() System Call
26.1.2 The waitpid() System Call
26.1.3 The Wait Status Value
26.1.4 Process Termination from a Signal Handler
26.1.5 The waitid() System Call
26.1.6 The wait3() and wait4() System Calls
26.2 Orphans and Zombies
26.3 The SIGCHLD Signal
26.3.1 Establishing a Handler for SIGCHLD
26.3.2 Delivery of SIGCHLD for Stopped Children
26.3.3 Ignoring Dead Child Processes
26.4 Summary
26.5 Exercises
2009-08-26
Chapter 25: Process Termination
This chapter describes what happens when a process terminates. We begin by describing the use of exit() and _exit() to terminate a process. We discuss the use of exit handlers to automatically perform cleanups when a process calls exit(). We also consider some interactions between fork(), stdio buffers, and exit().
25 Process Termination
25.1 Terminating a Process: _exit() and exit()
25.2 Details of Process Termination
25.3 Exit Handlers
25.4 Interactions Between fork(), stdio Buffers, and _exit()
25.5 Summary
25.6 Exercises
25 Process Termination
25.1 Terminating a Process: _exit() and exit()
25.2 Details of Process Termination
25.3 Exit Handlers
25.4 Interactions Between fork(), stdio Buffers, and _exit()
25.5 Summary
25.6 Exercises
2009-08-25
Chapter 24: Process Creation
In this and the next three chapters, we look at how a process is created and terminates, and how a process can execute a new program. This chapter covers process creation. However, before diving into that subject, we present a short overview of the main system calls covered in these four chapters.
24 Process Creation
24.1 Overview of fork(), exit(), wait(), and execve()
24.2 Creating a New Process: fork()
24.2.1 File Sharing Between Parent and Child
24.2.2 Memory Semantics of fork()
24.3 The vfork() System Call
24.4 Race Conditions after fork()
24.5 Avoiding Race Conditions by Synchronizing with Signals
24.6 Summary
24.7 Exercises
24 Process Creation
24.1 Overview of fork(), exit(), wait(), and execve()
24.2 Creating a New Process: fork()
24.2.1 File Sharing Between Parent and Child
24.2.2 Memory Semantics of fork()
24.3 The vfork() System Call
24.4 Race Conditions after fork()
24.5 Avoiding Race Conditions by Synchronizing with Signals
24.6 Summary
24.7 Exercises
2009-08-24
Chapter 23: Timers and Sleeping
A timer allows a process to schedule a notification for itself to occur at some time in the future. Sleeping allows a process (or thread) to suspend execution for a period of time. This chapter describes the interfaces used for setting timers and for sleeping. It covers the following topics:
23 Timers and Sleeping
23.1 Interval Timers
23.2 Scheduling and Accuracy of Timers
23.3 Setting Timeouts on Blocking Operations
23.4 Suspending Execution for a Fixed Interval (Sleeping)
23.4.1 Low-resolution Sleeping: sleep()
23.4.2 High-resolution Sleeping: nanosleep()
23.5 POSIX Clocks
23.5.1 Retrieving the Value of a Clock: timer_gettime()
23.5.2 Updating the Value of a Clock: timer_gettime()
23.5.3 Obtaining the Clock ID of a Specific Process or Thread
23.5.4 Improved High-resolution Sleeping: clock_nanosleep()
23.6 POSIX Interval Timers
23.6.1 Creating a Timer: timer_create()
23.6.2 Arming and Disarming a Timer: timer_settime()
23.6.3 Retrieving the Current Value of a Timer: timer_gettime()
23.6.4 Deleting a Timer: timer_delete()
23.6.5 Notification via a Signal (SIGEV_SIGNAL)
23.6.6 Timer Overruns
23.6.7 Notification via a Thread (SIGEV_THREAD)
23.7 Timers That Notify via File Descriptors: the timerfd API
23.8 Summary
23.9 Exercises
- the classical Unix APIs for setting interval timers (setitimer() and alarm()) to notify a process when a certain amount of time has passed;
- the APIs that allow a process to sleep for a specified interval;
- the POSIX.1b clocks and timers APIs; and
- the Linux-specific timerfd facility, which allows the creation of timers whose expirations can be read from a file descriptor.
23 Timers and Sleeping
23.1 Interval Timers
23.2 Scheduling and Accuracy of Timers
23.3 Setting Timeouts on Blocking Operations
23.4 Suspending Execution for a Fixed Interval (Sleeping)
23.4.1 Low-resolution Sleeping: sleep()
23.4.2 High-resolution Sleeping: nanosleep()
23.5 POSIX Clocks
23.5.1 Retrieving the Value of a Clock: timer_gettime()
23.5.2 Updating the Value of a Clock: timer_gettime()
23.5.3 Obtaining the Clock ID of a Specific Process or Thread
23.5.4 Improved High-resolution Sleeping: clock_nanosleep()
23.6 POSIX Interval Timers
23.6.1 Creating a Timer: timer_create()
23.6.2 Arming and Disarming a Timer: timer_settime()
23.6.3 Retrieving the Current Value of a Timer: timer_gettime()
23.6.4 Deleting a Timer: timer_delete()
23.6.5 Notification via a Signal (SIGEV_SIGNAL)
23.6.6 Timer Overruns
23.6.7 Notification via a Thread (SIGEV_THREAD)
23.7 Timers That Notify via File Descriptors: the timerfd API
23.8 Summary
23.9 Exercises
2009-08-22
Chapter 34 is in copyedit
Chapters 29 to 33 are back from copyedit. Chapter 34 has gone to copyedit.
2009-08-21
Chapter 22: Signals: Advanced Features
In this chapter, we continue our discussion of signals, covering a number of more advanced topics, including:
22 Signals: Advanced Features
22.1 Core Dump Files
22.2 Special Cases for Signal Delivery, Disposition, and Handling
22.3 Interruptible and Uninterruptible Process Sleep States
22.4 Hardware-generated Signals
22.5 Synchronous and Asynchronous Signal Generation
22.6 Timing and Order of Signal Delivery
22.7 Implementation and Portability of signal()
22.8 Realtime Signals
22.8.1 Sending Realtime Signals
22.8.2 Handling Realtime Signals
22.9 Waiting for a Signal Using a Mask: sigsuspend()
22.10 Synchronously Waiting for a Signal
22.11 Fetching Signals via a File Descriptor
22.12 Interprocess Communication with Signals
22.13 Earlier Signal APIs (System V and BSD)
22.14 Summary
22.15 Exercises
- core dump files;
- special cases regarding signal delivery, disposition, and handling;
- synchronous and asynchronous generation of signals;
- when and in what order signals are delivered;
- interruption of system calls by signal handlers, and how to automatically restart interrupted system calls;
- realtime signals;
- using sigsuspend() to set the process signal mask wait for a signal to arrive;
- using sigwaitinfo() (and sigtimedwait()) to synchronously wait for a signal to arrive;
- using signalfd() to receive a signal via file descriptor; and
- the older BSD and System V signal APIs.
22 Signals: Advanced Features
22.1 Core Dump Files
22.2 Special Cases for Signal Delivery, Disposition, and Handling
22.3 Interruptible and Uninterruptible Process Sleep States
22.4 Hardware-generated Signals
22.5 Synchronous and Asynchronous Signal Generation
22.6 Timing and Order of Signal Delivery
22.7 Implementation and Portability of signal()
22.8 Realtime Signals
22.8.1 Sending Realtime Signals
22.8.2 Handling Realtime Signals
22.9 Waiting for a Signal Using a Mask: sigsuspend()
22.10 Synchronously Waiting for a Signal
22.11 Fetching Signals via a File Descriptor
22.12 Interprocess Communication with Signals
22.13 Earlier Signal APIs (System V and BSD)
22.14 Summary
22.15 Exercises
2009-08-20
Chapter 21: Signals: Signal Handlers
This chapter continues the description of signals begun in the previous chapter. It focuses on signal handlers, and extends the discussion started in Section 20.4. Among the topics we consider are the following:
21 Signals: Signal Handlers
21.1 Designing Signal Handlers
21.1.1 Signals Are Not Queued (Revisited)
21.1.2 Reentrant and Async-signal-safe Functions
21.1.3 Global Variables and the sig_atomic_t Data Type
21.2 Other Methods of Terminating a Signal Handler
21.2.1 Performing a Nonlocal Goto from a Signal Handler
21.2.2 Terminating a Process Abnormally: abort()
21.3 Handling a Signal on an Alternate Stack: sigaltstack()
21.4 The SA_SIGINFO Flag
21.5 Interruption and Restarting of System Calls
21.6 Summary
21.7 Exercises
- how to design a signal handler, which necessitates a discussion of reentrancy and async-signal-safe functions;
- alternatives to performing a normal return from a signal handler, in particular, the use of a nonlocal goto for this purpose;
- handling of signals on an alternate stack;
- the use of the sigaction() SA_SIGINFO flag to allow a signal handler to obtain more detailed information about the signal that caused its invocation; and
- how a blocking system call may be interrupted by a signal handler, and how the call can be restarted if desired.
21 Signals: Signal Handlers
21.1 Designing Signal Handlers
21.1.1 Signals Are Not Queued (Revisited)
21.1.2 Reentrant and Async-signal-safe Functions
21.1.3 Global Variables and the sig_atomic_t Data Type
21.2 Other Methods of Terminating a Signal Handler
21.2.1 Performing a Nonlocal Goto from a Signal Handler
21.2.2 Terminating a Process Abnormally: abort()
21.3 Handling a Signal on an Alternate Stack: sigaltstack()
21.4 The SA_SIGINFO Flag
21.5 Interruption and Restarting of System Calls
21.6 Summary
21.7 Exercises
Chapter 20: Signals: Fundamental Concepts
This chapter and next two chapters discuss signals. Although the fundamental concepts are quite simple, our discussion is quite lengthy, since there are many details to cover.
This chapter covers the following topics:
20.1 Concepts and Overview
20.2 Signal Types and Default Actions
20.3 Changing Signal Dispositions: signal()
20.4 Introduction to Signal Handlers
20.5 Sending Signals: kill()
20.6 Checking for the Existence of a Process
20.7 Other Ways of Sending Signals: raise() and killpg()
20.8 Displaying Signal Descriptions
20.9 Signal Sets
20.10 The Signal Mask (Blocking Signal Delivery)
20.11 Pending Signals
20.12 Signals Are Not Queued
20.13 Changing Signal Dispositions: sigaction()
20.14 Waiting for a Signal: pause()
20.15 Summary
20.16 Exercises
This chapter covers the following topics:
- the various different signals and their purposes;
- the circumstances in which the kernel may generate a signal for a process, and the system calls that one process may use to send a signal to another process;
- how a process responds to a signal by default, and the means by which a process can change its response to a signal, in particular, through the use of a signal handler, a programmer-defined function that is automatically invoked on receipt of a signal;
- the use of a process signal mask to block signals, and the associated notion of pending signals; and
- how a process can suspend execution and wait for the delivery of a signal.
20.1 Concepts and Overview
20.2 Signal Types and Default Actions
20.3 Changing Signal Dispositions: signal()
20.4 Introduction to Signal Handlers
20.5 Sending Signals: kill()
20.6 Checking for the Existence of a Process
20.7 Other Ways of Sending Signals: raise() and killpg()
20.8 Displaying Signal Descriptions
20.9 Signal Sets
20.10 The Signal Mask (Blocking Signal Delivery)
20.11 Pending Signals
20.12 Signals Are Not Queued
20.13 Changing Signal Dispositions: sigaction()
20.14 Waiting for a Signal: pause()
20.15 Summary
20.16 Exercises
2009-08-19
Chapter 19: Monitoring File Events
Some applications need to be able to monitor files or directories in order to determine whether events have occurred for the monitored objects. For example, a graphical file manager needs to be able to determine when files are added or removed from the directory that is currently being displayed, or a daemon may want to monitor its configuration file in order to know if the file has been changed.
Starting with kernel 2.6.13, Linux provides the inotify mechanism, which allows an application to monitor file events. This chapter describes the use of inotify.
19 Monitoring File Events
19.1 Overview
19.2 The inotify API
19.3 inotify Events
19.4 Reading inotify Events
19.5 Queue Limits and /proc Files
19.6 An Older System for Monitoring File Events: dnotify
19.7 Summary
19.8 Exercises
Starting with kernel 2.6.13, Linux provides the inotify mechanism, which allows an application to monitor file events. This chapter describes the use of inotify.
19 Monitoring File Events
19.1 Overview
19.2 The inotify API
19.3 inotify Events
19.4 Reading inotify Events
19.5 Queue Limits and /proc Files
19.6 An Older System for Monitoring File Events: dnotify
19.7 Summary
19.8 Exercises
Subscribe to:
Posts (Atom)
