2009-09-30

Chapters 1 to 42

Copyediting is now completed through to chapter 42, and thus is complete for five of the eight logical parts of my book (see this earlier post). So, here's an updated version of the detailed table of contents so far.

1 History and Standards [~20 pages]
1.1 A Brief History of Unix and C
1.2 A Brief History of Linux
        1.2.1 The GNU Project
        1.2.2 The Linux Kernel
1.3 Standardization
        1.3.1 The C Programming Language
        1.3.2 The First POSIX Standards
        1.3.3 X/Open Company and The Open Group
        1.3.4 SUSv3 and POSIX.1-2001
        1.3.5 SUSv4 and POSIX.1-2008
        1.3.6 Unix Standards Timeline
        1.3.7 Implementation Standards
        1.3.8 Linux, Standards, and the Linux Standard Base
1.4 Summary

2 Fundamental Concepts [~20 pages]
2.1 The Core Operating System: The Kernel
2.2 The Shell
2.3 Users and Groups
2.4 Single Directory Hierarchy, Directories, Links, and Files
2.5 File I/O Model
2.6 Programs
2.7 Processes
2.8 Memory Mappings
2.9 Static and Shared Libraries
2.10 Interprocess Communication and Synchronization
2.11 Signals
2.12 Threads
2.13 Process Groups and Shell Job Control
2.14 Sessions, Controlling Terminals, and Controlling Processes
2.15 Pseudoterminals
2.16 Date and Time
2.17 Client-server Architecture
2.18 Realtime
2.19 The /proc File System
2.20 Summary

3 System Programming Concepts [~25 pages]
3.1 System Calls
3.2 Library Functions
3.3 The Standard C Library; The GNU C Library (glibc)
3.4 Handling Errors from System Calls and Library Functions
3.5 Notes on the Example Programs in This Book
        3.5.1 Command-line Options and Arguments
        3.5.2 Common Functions and Header Files
3.6 Portability Issues
        3.6.1 Feature Test Macros
        3.6.2 System Data Types
        3.6.3 Miscellaneous Portability Issues
3.7 Summary
3.8 Exercises

4 File I/O: The Universal I/O Model [~20 pages]
4.1 Overview
4.2 Universality of I/O
4.3 Opening a File: open()
4.4 Reading from a File: read()
4.5 Writing to a File: write()
4.6 Closing a File: close()
4.7 Changing the Current File Offset: lseek()
4.8 Operations Outside the Universal I/O Model: ioctl()
4.9 Summary
4.10 Exercises

5 File I/O: Further Details [~25 pages]
5.1 Atomicity and Race Conditions
5.2 File Control Operations: fcntl()
5.3 Open File Status Flags
5.4 Relationship Between File Descriptors and Open Files
5.5 Duplicating File Descriptors
5.6 File I/O at a Specified Offset: pread() and pwrite()
5.7 Scatter-gather I/O: readv() and writev()
5.8 Truncating a File: truncate() and ftruncate()
5.9 Nonblocking I/O
5.10 I/O on Large Files
5.11 The /dev/fd Directory
5.12 Creating Temporary Files
5.13 Summary
5.14 Exercises

6 Processes [~25 pages]
6.1 Processes and Programs
6.2 Process ID and Parent Process ID
6.3 Memory Layout of a Process
6.4 Virtual Memory Management
6.5 The Stack and Stack Frames
6.6 Command-line Arguments (argc, argv)
6.7 Environment List
6.8 Performing a Nonlocal Goto: setjmp() and longjmp()
6.9 Summary
6.10 Exercises

7 Memory Allocation [~15 pages]
7.1 Allocating Memory on the Heap
        7.1.1 Adjusting the Program Break: brk() and sbrk()
        7.1.2 Allocating Memory on the Heap: malloc() and free()
        7.1.3 Implementation of malloc() and free()
        7.1.4 Other Methods of Allocating Memory on the Heap
7.2 Allocating Memory on the Stack: alloca()
7.3 Summary
7.4 Exercises

8 Users and Groups [~15 pages]
8.1 The Password File: /etc/passwd
8.2 The Shadow Password File: /etc/shadow
8.3 The Group File: /etc/group
8.4 Retrieving User and Group Information
8.5 Password Encryption and User Authentication
8.6 Summary
8.7 Exercises

9 Process Credentials [~20 pages]
9.1 Real User ID and Real Group ID
9.2 Effective User ID and Effective Group ID
9.3 Set-user-ID and Set-group-ID Programs
9.4 Saved Set-user-ID and Saved Set-group-ID
9.5 File System User ID and File System Group ID
9.6 Supplementary Group IDs
9.7 Retrieving and Modifying Process Credentials
        9.7.1 Retrieving and Modifying Real, Effective, and Saved Set IDs
        9.7.2 Retrieving and Modifying File System IDs
        9.7.3 Retrieving and Modifying Supplementary Group IDs
        9.7.4 Summary of Calls for Modifying Process Credentials
        9.7.5 Example: Displaying Process Credentials
9.8 Summary
9.9 Exercises

10 Times and Dates [~25 pages]
10.1 Calendar Time
10.2 Time-Conversion Functions
        10.2.1 Converting time_t to Printable Form
        10.2.2 Converting Between time_t and Broken-down Time
        10.2.3 Converting Between Broken-down Time and Printable Form
10.3 Timezones
10.4 Locales
10.5 Updating the System Clock
10.6 The Software Clock (Jiffies)
10.7 Process Time
10.8 Summary
10.9 Exercises

11 System Limits and Options [~10 pages]
11.1 System Limits
11.2 Retrieving System Limits (and Options) at Run Time
11.3 Retrieving File-related Limits (and Options) at Run Time
11.4 Indeterminate Limits
11.5 System Options
11.6 Summary
11.7 Exercises

12 System and Process Information [~10 pages]
12.1 The /proc File System
        12.1.1 Obtaining Information about a Process: /proc/PID
        12.1.2 System Information under /proc
        12.1.3 Accessing /proc Files
12.2 System Identification: uname()
12.3 Summary
12.4 Exercises

13 File I/O Buffering [~20 pages]
13.1 Kernel Buffering of File I/O: The Buffer Cache
13.2 Buffering in the stdio Library
13.3 Controlling Kernel Buffering of File I/O
13.4 Summary of I/O Buffering
13.5 Giving the Kernel Hints about I/O Patterns: posix_fadvise()
13.6 Bypassing the Buffer Cache: Direct I/O
13.7 Mixing Library Functions and System Calls for File I/O
13.8 Summary
13.9 Exercises

14 File Systems [~30 pages]
14.1 Device Special Files (Devices)
14.2 Disks and Partitions
14.3 File Systems
14.4 I-nodes
14.5 The Virtual File System (VFS)
14.6 Journaling File Systems
14.7 Single Directory Hierarchy and Mount Points
14.8 Mounting and Unmounting File Systems
14.8.1 Mounting a File System: mount()
14.8.2 Unmounting a File System: umount() and umount2()
14.9 Advanced Mount Features
14.9.1 Mounting a File System at Multiple Mount Points
14.9.2 Stacking Multiple Mounts on the Same Mount Point
14.9.3 Mount Flags That Are Per-mount Options
14.9.4 Bind Mounts
14.9.5 Recursive Bind Mounts
14.10 A Virtual Memory File System: tmpfs
14.11 Obtaining Information about a File System: statvfs()
14.12 Summary
14.13 Exercises

15 File Attributes [~30 pages]
15.1 Retrieving File Information: stat()
15.2 File Timestamps
        15.2.1 Changing File Timestamps with utime() and utimes()
        15.2.2 Changing File Timestamps with utimensat() and futimens()
15.3 File Ownership
        15.3.1 Ownership of New Files
        15.3.2 Changing File Ownership: chown(), fchown(), and lchown()
15.4 File Permissions
        15.4.1 Permissions on Regular Files
        15.4.2 Permissions on Directories
        15.4.3 Permission Checking Algorithm
        15.4.4 Checking File Accessibility: access()
        15.4.5 Set-user-ID, Set-group-ID, and Sticky Bits
        15.4.6 The Process File Mode Creation Mask: umask()
        15.4.7 Changing File Permissions: chmod() and fchmod()
15.5 I-node Flags (ext2 Extended File Attributes)
15.6 Summary
15.7 Exercises

16 Extended Attributes [~8 pages]
16.1 Overview
16.2 Extended Attribute Implementation Details
16.3 System Calls for Manipulating Extended Attributes
16.4 Summary
16.5 Exercises

17 Access Control Lists [~20 pages]
17.1 Overview
17.2 ACL Permission-Checking Algorithm
17.3 Long and Short Text Forms for ACLs
17.4 The ACL_MASK Entry and the ACL Group Class
17.5 The getfacl and setfacl Commands
17.6 Default ACLs and File Creation
17.7 ACL Implementation Limits
17.8 The ACL API
17.9 Summary
17.10 Exercises

18 Directories and Links [~35 pages]
18.1 Directories and (Hard) Links
18.2 Symbolic (Soft) Links
18.3 Creating and Removing (Hard) Links: link() and unlink()
18.4 Changing the Name of a File: rename()
18.5 Working with Symbolic Links: symlink() and readlink()
18.6 Creating and Removing Directories: mkdir() and rmdir()
18.7 Removing a File or Directory: remove()
18.8 Reading Directories: opendir() and readdir()
18.9 File Tree Walking: nftw()
18.10 The Current Working Directory of a Process
18.11 Operating Relative to a Directory File Descriptor
18.12 Changing the Root Directory of a Process: chroot()
18.13 Resolving a Pathname: realpath()
18.14 Parsing Pathname Strings: dirname() and basename()
18.15 Summary
18.16 Exercises

19 Monitoring File Events [~12 pages]
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

20 Signals: Fundamental Concepts [~30 pages]
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

21 Signals: Signal Handlers [~25 pages]
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

22 Signals: Advanced Features [~30 pages]
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

23 Timers and Sleeping [~30 pages]
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

24 Process Creation [~20 pages]
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

25 Process Termination [~10 pages]
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

26 Monitoring Child Processes [~20 pages]
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

27 Program Execution [~20 pages]
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

28 Process Creation and Program Execution in More Detail [~25 pages]
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

29 Threads: Introduction [~15 pages]
29.1 Overview
29.2 Background Details of the Pthreads API
29.3 Thread Creation
29.4 Thread Termination
29.5 Thread IDs
29.6 Joining with a Terminated Thread: pthread_join()
29.7 Detaching a Thread: pthread_detach()
29.8 Thread Attributes
29.9 Threads Versus Processes
29.10 Summary
29.11 Exercises


30 Threads: Thread Synchronization [~25 pages]
30.1 Protecting Accesses to Shared Variables: Mutexes
        30.1.1 Statically Allocated Mutexes
        30.1.2 Locking and Unlocking a Mutex
        30.1.3 Performance of Mutexes
        30.1.4 Mutex Deadlocks
        30.1.5 Dynamically Initializing a Mutex
        30.1.6 Mutex Attributes
        30.1.7 Mutex Types
30.2 Signaling Changes of State: Condition Variables
        30.2.1 Statically Allocated Condition Variables
        30.2.2 Signaling and Waiting on Condition Variables
        30.2.3 Testing a Condition Variable’s Predicate
        30.2.4 Example Program: Joining Any Terminated Thread
        30.2.5 Dynamically Allocated Condition Variables
30.3 Summary
30.4 Exercises

31 Threads: Thread Safety and Per-thread Storage [~15 pages]
31.1 Thread Safety (and Reentrancy Revisited)
31.2 One-time Initialization
31.3 Thread-specific Data
        31.3.1 Thread-specific Data from the Library Function’s Perspective
        31.3.2 Overview of the Thread-specific Data API
        31.3.3 Details of the Thread-specific Data API
        31.3.4 Employing the Thread-specific Data API
        31.3.5 Thread-specific Data Implementation Limits
31.4 Thread-local Storage
31.5 Summary
31.6 Exercises

32 Threads: Thread Cancellation [~10 pages]
32.1 Canceling a Thread
32.2 Cancellation State and Type
32.3 Cancellation Points
32.4 Testing for Thread Cancellation
32.5 Cleanup Handlers
32.6 Asynchronous Cancelability
32.7 Summary
32.8 Exercises

33 Threads: Further Details [~15 pages]
33.1 Thread Stacks
33.2 Threads and Signals
        33.2.1 How the Unix Signal Model Maps to Threads
        33.2.2 Manipulating the Thread Signal Mask
        33.2.3 Sending a Signal to a Thread
        33.2.4 Dealing with Asynchronous Signals Sanely
33.3 Threads and Process Control
33.4 Thread Implementation Models
33.5 Linux Implementations of POSIX Threads
        33.5.1 LinuxThreads
        33.5.2 NPTL
        33.5.3 Which Threading Implementation?
33.6 Advanced Features of the Pthreads API
33.7 Summary
33.8 Exercises

34 Process Groups, Sessions, and Job Control [~35 pages]
34.1 Overview
34.2 Process Groups
34.3 Sessions
34.4 Controlling Terminals and Controlling Processes
34.5 Foreground and Background Process Groups
34.6 The SIGHUP Signal
        34.6.1 Handling of SIGHUP by the Shell
        34.6.2 SIGHUP and Termination of the Controlling Process
34.7 Job Control
        34.7.1 Using Job Control within the Shell
        34.7.2 Implementing Job Control
        34.7.3 Handling Job-control Signals
        34.7.4 Orphaned Process Groups (and SIGHUP Revisited)
34.8 Summary
34.9 Exercises

35 Process Priorities and Scheduling [~20 pages]
35.1 Process Priorities (Nice Values)
35.2 Overview of Realtime Process Scheduling
        35.2.1 The SCHED_RR Policy
        35.2.2 The SCHED_FIFO Policy
        35.2.3 The SCHED_BATCH and SCHED_IDLE Policies
35.3 Realtime Process Scheduling API
        35.3.1 Realtime Priority Ranges
        35.3.2 Modifying and Retrieving Policies and Priorities
        35.3.3 Relinquishing the CPU
        35.3.4 The SCHED_RR Time Slice
35.4 CPU Affinity
35.5 Summary
35.6 Exercises

36 Process Resources [~15 pages]
36.1 Process Resource Usage: getrusage()
36.2 Process Resource Limits: getrlimit() and setrlimit()
36.3 Details of Specific Resource Limits
36.4 Summary
36.5 Exercises

37 Daemons [~15 pages]
37.1 Overview
37.2 Creating a Daemon
37.3 Guidelines for Writing Daemons
37.4 Using SIGHUP to Reinitialize a Daemon
37.5 Logging Messages and Errors Using syslog
37.5.1 Overview
37.5.2 The syslog API
37.5.3 The /etc/syslog.conf File
37.6 Summary
37.7 Exercises

38 Writing Secure Privileged Programs [~15 pages]
38.1 A Checklist for Secure Programming
38.2 Summary
38.3 Exercises

39 Capabilities [~20 pages]
39.1 Rationale for Capabilities
39.2 The Linux Capabilities
39.3 Process and File Capabilities
39.3.1 Process Capabilities
39.3.2 File Capabilities
39.3.3 Purpose of the Process Permitted and Effective Capability Sets
39.3.4 Purpose of the File Permitted and Effective Capability Sets
39.3.5 Purpose of the Process and File Inheritable Sets
39.3.6 Assigning and Viewing File Capabilities from the Shell
39.4 The Modern Capabilities Implementation
39.5 Transformation of Process Capabilities during exec()
39.5.1 Capability Bounding Set
39.5.2 Preserving root Semantics
39.6 Effect on Process Capabilities of Changing User IDs
39.7 Changing Process Capabilities Programmatically
39.8 Creating Capabilities-only Environments
39.9 Discovering the Capabilities Required by a Program
39.10 Older Kernels and Systems without File Capabilities
39.11 Summary
39.12 Exercises

40 Login Accounting [~15 pages]
40.1 Overview of the utmp and wtmp Files
40.2 The utmpx API
40.3 The utmpx Structure
40.4 Retrieving Information from the utmp and wtmp Files
40.5 Retrieving the Login Name: getlogin()
40.6 Updating the utmp and wtmp Files for a Login Session
40.7 The lastlog File
40.8 Summary
40.9 Exercises

41 Fundamentals of Shared Libraries [~25 pages]
41.1 Object Libraries
41.2 Static Libraries
41.3 Overview of Shared Libraries
41.4 Creating and Using Shared Libraries--A First Pass
        41.4.1 Creating a Shared Library
        41.4.2 Position-independent Code
        41.4.3 Using a Shared Library
        41.4.4 The Shared Library Soname
41.5 Useful Tools for Working with Shared Libraries
41.6 Shared Library Versions and Naming Conventions
41.7 Installing Shared Libraries
41.8 Compatible Versus Incompatible Libraries
41.9 Upgrading Shared Libraries
41.10 Specifying Library Search Directories in an Object File
41.11 Finding Shared Libraries at Run Time
41.12 Run-time Symbol Resolution
41.13 Using a Static Library Instead of a Shared Library
41.14 Summary
41.15 Exercises

42 Advanced Features of Shared Libraries [~20 pages]
42.1 Dynamically Loaded Libraries
        42.1.1 Opening a Shared Library
        42.1.2 Diagnosing Errors from the dlopen API
        42.1.3 Obtaining the Address of a Symbol: dlsym()
        42.1.4 Closing a Shared Library: dlclose()
        42.1.5 Obtaining Information about Loaded Symbols: dladdr()
        42.1.6 Accessing Symbols in the Main Program
42.2 Controlling Symbol Visibility
42.3 Linker Version Scripts
        42.3.1 Controlling Symbol Visibility with Version Scripts
        42.3.2 Symbol Versioning
42.4 Initialization and Finalization Functions
42.5 Preloading Shared Libraries
42.6 Monitoring the Dynamic Linker: LD_DEBUG
42.7 Summary
42.8 Exercises

2009-09-29

Chapter 42: Advanced Features of Shared Libraries

The previous chapter covered the fundamentals of shared libraries. This chapter describes a number of advanced features of shared libraries, including the following:
  • dynamically loading shared libraries;
  • controlling the visibility of symbols defined by a shared library;
  • using linker scripts to create versioned symbols;
  • using initialization and finalization functions to automatically execute code when a library is loaded and unloaded;
  • shared library preloading; and
  • using LD_DEBUG to monitor the operation of the dynamic linker.
42 Advanced Features of Shared Libraries
42.1 Dynamically Loaded Libraries
        42.1.1 Opening a Shared Library
        42.1.2 Diagnosing Errors from the dlopen API
        42.1.3 Obtaining the Address of a Symbol: dlsym()
        42.1.4 Closing a Shared Library: dlclose()
        42.1.5 Obtaining Information about Loaded Symbols: dladdr()
        42.1.6 Accessing Symbols in the Main Program
42.2 Controlling Symbol Visibility
42.3 Linker Version Scripts
        42.3.1 Controlling Symbol Visibility with Version Scripts
        42.3.2 Symbol Versioning
42.4 Initialization and Finalization Functions
42.5 Preloading Shared Libraries
42.6 Monitoring the Dynamic Linker: LD_DEBUG
42.7 Summary
42.8 Exercises

2009-09-28

See you at LCA 2010!

One of my proposals got accepted for LCA 2010, in Wellington, New Zealand! As usual, there look to be lots of interesting papers at LCA. I'm presenting a tutorial on writing secure privileged programs, which will draw heavily on Chapter 38 of my book.

2009-09-24

Capter 41: Fundamentals of Shared Libraries

Shared libraries are a technique for placing library functions into a single unit that can be shared by multiple processes at run time. This technique can save both disk space and RAM. This chapter covers the fundamentals of shared libraries. The next chapter covers a number of advanced features of shared libraries.

41 Fundamentals of Shared Libraries
41.1 Object Libraries
41.2 Static Libraries
41.3 Overview of Shared Libraries
41.4 Creating and Using Shared Libraries--A First Pass
        41.4.1 Creating a Shared Library
        41.4.2 Position-independent Code
        41.4.3 Using a Shared Library
        41.4.4 The Shared Library Soname
41.5 Useful Tools for Working with Shared Libraries
41.6 Shared Library Versions and Naming Conventions
41.7 Installing Shared Libraries
41.8 Compatible Versus Incompatible Libraries
41.9 Upgrading Shared Libraries
41.10 Specifying Library Search Directories in an Object File
41.11 Finding Shared Libraries at Run Time
41.12 Run-time Symbol Resolution
41.13 Using a Static Library Instead of a Shared Library
41.14 Summary
41.15 Exercises

2009-09-22

Chapter 40: Login Accounting

Login accounting is concerned with recording which users are currently logged in to the system, and recording past logins and logouts. This chapter looks at the login accounting files and the library functions used to retrieve and update the information they contain. We also describe the steps that an application providing a login service should perform in order to update these files when a user logs in and out.

40 Login Accounting
40.1 Overview of the utmp and wtmp Files
40.2 The utmpx API
40.3 The utmpx Structure
40.4 Retrieving Information from the utmp and wtmp Files
40.5 Retrieving the Login Name: getlogin()
40.6 Updating the utmp and wtmp Files for a Login Session
40.7 The lastlog File
40.8 Summary
40.9 Exercises

2009-09-21

Chapter 39: Capabilities

This chapter describes the Linux capabilities scheme, which divides the traditional all-or-nothing Unix privilege scheme into individual capabilities that can be independently enabled or disabled. Using capabilities allows a program to perform some privileged operations, while preventing it from performing others.

39 Capabilities
39.1 Rationale for Capabilities
39.2 The Linux Capabilities
39.3 Process and File Capabilities
39.3.1 Process Capabilities
39.3.2 File Capabilities
39.3.3 Purpose of the Process Permitted and Effective Capability Sets
39.3.4 Purpose of the File Permitted and Effective Capability Sets
39.3.5 Purpose of the Process and File Inheritable Sets
39.3.6 Assigning and Viewing File Capabilities from the Shell
39.4 The Modern Capabilities Implementation
39.5 Transformation of Process Capabilities during exec()
39.5.1 Capability Bounding Set
39.5.2 Preserving root Semantics
39.6 Effect on Process Capabilities of Changing User IDs
39.7 Changing Process Capabilities Programmatically
39.8 Creating Capabilities-only Environments
39.9 Discovering the Capabilities Required by a Program
39.10 Older Kernels and Systems without File Capabilities
39.11 Summary
39.12 Exercises

2009-09-19

Chapters 43 to 44 are in copyedit

Chapters 41 and 42 already went to copyedit a while back, and by now chapters 37 to 42 came back from copyedit. Chapters 43 and 44 are now in copyedit.

2009-09-17

Chapter 38: Writing Secure Privileged Programs

Privileged programs have access to features and resources (files, devices, and so on) that are not available to ordinary users. A program can run with privileges by two general means:
  • The program was started under a privileged user ID. Many daemons and network servers, which are typically run as root, fall into this category.
  • The program has its set-user-ID or set-group-ID permission bit set. When a set-user-ID (set-group-ID) program is execed, it changes the effective user (group) ID of the process to be the same as the owner (group) of the program file.
If a privileged program contains bugs, or can be subverted by a malicious user, then the security of the system or an application can be compromised. From a security viewpoint, we should write programs so as to minimize both the chance of a compromise and the damage that can be done if a compromise does occur. These topics form the subject of this chapter.

38 Writing Secure Privileged Programs
38.1 A Checklist for Secure Programming
38.2 Summary
38.3 Exercises

2009-09-16

Chapter 37: Daemons

This chapter examines the characteristics of daemon processes and looks at the steps required to turn a process into a daemon. We also look at how to log messages from a daemon using the syslog facility.

37 Daemons
37.1 Overview
37.2 Creating a Daemon
37.3 Guidelines for Writing Daemons
37.4 Using SIGHUP to Reinitialize a Daemon
37.5 Logging Messages and Errors Using syslog
37.5.1 Overview
37.5.2 The syslog API
37.5.3 The /etc/syslog.conf File
37.6 Summary
37.7 Exercises

2009-09-14

Chapter 36: Process Resources

Each process consumes system resources such as memory and CPU time. This chapter looks at resource-related system calls. We begin with the getrusage() system call, which allows a process to monitor the resources that it has used or that its children have used. We then look at the setrlimit() and getrlimit() system calls, which can be used to change and retrieve limits on the calling process's consumption of various resources.

36 Process Resources
36.1 Process Resource Usage: getrusage()
36.2 Process Resource Limits: getrlimit() and setrlimit()
36.3 Details of Specific Resource Limits
36.4 Summary
36.5 Exercises

2009-09-08

Choosing a title for the book

No Starch Press and I have been kicking around some ideas for the title of the book, but so far we've still not settled on one. And I'm curious what other people might think. So this blog post asks for readers' opinions on the candidates.

Before I mention the titles we've thought about, it's worth mentioning that a couple of possibly useful titles are already taken (since otherwise people might suggest them to me): Advanced Linux Programming (Mitchell et al., 2001, Sams) and Linux System Programming (Love, 2007, O’Reilly).

When thinking of the titles below, I try to keep in mind two important aspects to the title of a book (which are not always in perfect harmony):
  • Is the title an accurate reflection of the subject of the book?
  • Does the title help sell the book? For example, does it help the book get found in online searches? Is it memorable? Does it get good shelf placement in bookshops? And so on.
1. Linux System and Network Programming

This has been my working title for the book since its inception, and captures two points that are important for marketing:
  • The focus on Linux.
  • The inclusion of a significant section on network programming. This is important because there are whole books devoted to network programming (most obviously, the books of W. Richard Stevens) so there is an obvious market. Although the material that is purely about network programming is only about 10% of the book (i.e., 150 pages), the fact that a lot of related topics are covered (e.g., process creation, program execution, secure programming, I/O multiplexing, threaded programming) means that the book's coverage of network programming is in effect quite substantial.
Against this title choice:
  • It doesn't capture an important aspect of the book: the book focuses heavily on portability, and clearly delineates Linux extensions from "standard" Unix. This means the book really can be used by system programmers on other Unix systems. (The current version of the preface makes this point strongly.)
  • It could be confusing if I one day write a book whose subject is more purely "Linux Network Programming" (which is something I might one day do).
  • It could be considered a little prosaic.
2. Linux/UNIX System and Network Programming

This title attempts to keep "Network" while trying also to address the portable focus of the book. But is it a little clunky as a title?

3. Linux and UNIX System Programming

This title captures the book's focus on both Linux specifically and Unix generally: on the one hand, the book constantly drills down into the specifics of Linux, while on the other hand, it keeps a close eye on Unix standards and portability (and occasionally drills down into details about other Unix systems). (Again, see the preface.)

This title is more concise than Linux/UNIX System and Network Programming, but, conversely, it omits mention of the network programming component of the book. The question is, if we're going for a shorter title, is it more important from a marketing point of view to mention Unix or to mention networking?

Like Linux System and Network Programming, this title might be considered prosaic. On the other hand, it's solid, and could be a title that has a good shelf life.

4. The Craft of Linux Programming

I like this title quite a lot. It has a few resonances. One is the comparison of "craft" with "art", which carries over quite happily into computing. For example, Knuth’s The Art of Computer Programming is exactly that: a (magnificent) work of art about the fundamentals of computing. By contrast, my book is about a lot of the everyday tools that are required for the craft of system programming. In addition, the English word craft derives from the German Kraft (I'm not German, but I live in Germany). Kraft can be translated as power, which seems a reasonable summary of a goal of the book: to provide its readers with the power to write effective system programs.

The title is quirky, and maybe less searchable than others. On the other hand, it has the virtue of being distinctive. Stevens' classic had a somewhat quirky and distinctive title as well, one that distinguished it from the pack: Advanced Programming in the Unix Environment. So, in the end, I'm undecided about whether quirkiness is a marketing plus or minus.

5. Advanced Programming in the Linux Environment

Because of its resonance with another title, inevitably, I have to preface discussion of this title with a couple of remarks. First, it was not my idea (it was someone else's suggestion), and I was initially rather against it. Second, to my surprise, informal canvassing of some of my technical reviewers showed that several of them were quite warm to the title (and none of them disliked it), even though most (probably all) of them are well aware of the other book.

Of course, the title is a play on Stevens' Advanced Programming in the Unix Environment (which was in turn a play on an earlier quirkily titled classic, Kernighan & Pike, The Unix Programming Environment).

Against this title:
  • Maybe it looks presumptuous and/or cheeky to choose such an obviously close title.
  • It doesn't mention Unix or Network (see my comments on the other titles above).
For this title:
  • In terms of Linux titles, it's reasonably distinctive.
  • The flip side of cheeky and presumptuous is that the title is also a homage and conveys something of my intent in writing the book. Any book that tries to seriously cover the area of system programming on Unix-type systems owes a debt to Stevens' work, both in terms of the rich technical resources that his books provide, and in terms of the wonderful clarity of his writing. As a system programming text, my book certainly aims at something like the technical depth of Stevens (while at the same time: broadening the range of topics covered, addressing the latest standards, and providing in-depth specifics of the most widely-used Unix-type system). And I continue to be amazed by the clarity of his writing, and attempt to get somewhere close to that clarity (inevitably, it's hard for me to judge how well I've done on that score, since I'm too close to my own writing and ideas to be a good judge).
Summary

In summary, the titles that we're so far considering are the following:
  1. Linux System and Network Programming
  2. Linux/UNIX System and Network Programming
  3. Linux and UNIX System Programming
  4. The Craft of Linux Programming
  5. Advanced Programming in the Linux Environment
  6. Something else?
I'd be interested to hear your thoughts. You can send me votes and thoughts by email at mtk AT man7.org. You may also want to add comments to this blog post; but if you want to vote, I'd really prefer email. (Don't worry: I won't add you to any email list!) You can vote for as many titles as you like, but your vote will only make a meaningful difference if you vote for more than zero of the titles, and you don't vote for them all. Also, you might have ideas for other titles (option 6 above), or other thoughts about the titles I've listed above, and I’d welcome those.

Update: if you do email a vote to me, it would also be interesting to hear the reasons why you prefer or dislike certain titles. Thanks!

Chapter 35: Process Priorities and Scheduling

This chapter discusses various system calls and process attributes that determine when and which processes obtain access to the CPU(s). We begin by describing the nice value, a process characteristic that influences the amount of CPU time that a process is allocated by the kernel scheduler. We follow this with a description of the POSIX realtime scheduling API. This API allows us to define the policy and priority used for scheduling processes, giving us much tighter control over how processes are allocated to the CPU. We conclude with a discussion of the system calls for setting a process's CPU affinity mask, which determines the set of CPUs on which a process running on a multiprocessor system will run.

35 Process Priorities and Scheduling
35.1 Process Priorities (Nice Values)
35.2 Overview of Realtime Process Scheduling
35.2.1 The SCHED_RR Policy
35.2.2 The SCHED_FIFO Policy
35.2.3 The SCHED_BATCH and SCHED_IDLE Policies
35.3 Realtime Process Scheduling API
35.3.1 Realtime Priority Ranges
35.3.2 Modifying and Retrieving Policies and Priorities
35.3.3 Relinquishing the CPU
35.3.4 The SCHED_RR Time Slice
35.4 CPU Affinity
35.5 Summary
35.6 Exercises

2009-09-07

Chapter 34: Process Groups, Sessions, and Job Control

Process groups and sessions form a two-level hierarchical relationship between processes: a process group is a collection of related processes, and a session is a collection of related process groups. The meaning of the term related in each case is explained in the course of this chapter.

Process groups and sessions are abstractions defined to support shell job control, which allows interactive users to run commands in the foreground or in the background. The term job is often used synonymously with the term process group.

This chapter describes process groups, sessions, and job control.

34 Process Groups, Sessions, and Job Control
34.1 Overview
34.2 Process Groups
34.3 Sessions
34.4 Controlling Terminals and Controlling Processes
34.5 Foreground and Background Process Groups
34.6 The SIGHUP Signal
        34.6.1 Handling of SIGHUP by the Shell
        34.6.2 SIGHUP and Termination of the Controlling Process
34.7 Job Control
        34.7.1 Using Job Control within the Shell
        34.7.2 Implementing Job Control
        34.7.3 Handling Job-control Signals
        34.7.4 Orphaned Process Groups (and SIGHUP Revisited)
34.8 Summary
34.9 Exercises

2009-09-05

Chapters 1 to 33

Copyediting is quite a bit more work than I expected! But, we've now passed halfway: Chapters 1 to 33 form the first four of eight logical parts of my book (see this earlier post). So, this is a good point to post the detailed table of contents so far. Here's the current table of contents for these chapters.

1 History and Standards [~20 pages]
1.1 A Brief History of Unix and C
1.2 A Brief History of Linux
        1.2.1 The GNU Project
        1.2.2 The Linux Kernel
1.3 Standardization
        1.3.1 The C Programming Language
        1.3.2 The First POSIX Standards
        1.3.3 X/Open Company and The Open Group
        1.3.4 SUSv3 and POSIX.1-2001
        1.3.5 SUSv4 and POSIX.1-2008
        1.3.6 Unix Standards Timeline
        1.3.7 Implementation Standards
        1.3.8 Linux, Standards, and the Linux Standard Base
1.4 Summary

2 Fundamental Concepts [~20 pages]
2.1 The Core Operating System: The Kernel
2.2 The Shell
2.3 Users and Groups
2.4 Single Directory Hierarchy, Directories, Links, and Files
2.5 File I/O Model
2.6 Programs
2.7 Processes
2.8 Memory Mappings
2.9 Static and Shared Libraries
2.10 Interprocess Communication and Synchronization
2.11 Signals
2.12 Threads
2.13 Process Groups and Shell Job Control
2.14 Sessions, Controlling Terminals, and Controlling Processes
2.15 Pseudoterminals
2.16 Date and Time
2.17 Client-server Architecture
2.18 Realtime
2.19 The /proc File System
2.20 Summary

3 System Programming Concepts [~25 pages]
3.1 System Calls
3.2 Library Functions
3.3 The Standard C Library; The GNU C Library (glibc)
3.4 Handling Errors from System Calls and Library Functions
3.5 Notes on the Example Programs in This Book
        3.5.1 Command-line Options and Arguments
        3.5.2 Common Functions and Header Files
3.6 Portability Issues
        3.6.1 Feature Test Macros
        3.6.2 System Data Types
        3.6.3 Miscellaneous Portability Issues
3.7 Summary
3.8 Exercises

4 File I/O: The Universal I/O Model [~20 pages]
4.1 Overview
4.2 Universality of I/O
4.3 Opening a File: open()
4.4 Reading from a File: read()
4.5 Writing to a File: write()
4.6 Closing a File: close()
4.7 Changing the Current File Offset: lseek()
4.8 Operations Outside the Universal I/O Model: ioctl()
4.9 Summary
4.10 Exercises

5 File I/O: Further Details [~25 pages]
5.1 Atomicity and Race Conditions
5.2 File Control Operations: fcntl()
5.3 Open File Status Flags
5.4 Relationship Between File Descriptors and Open Files
5.5 Duplicating File Descriptors
5.6 File I/O at a Specified Offset: pread() and pwrite()
5.7 Scatter-gather I/O: readv() and writev()
5.8 Truncating a File: truncate() and ftruncate()
5.9 Nonblocking I/O
5.10 I/O on Large Files
5.11 The /dev/fd Directory
5.12 Creating Temporary Files
5.13 Summary
5.14 Exercises

6 Processes [~25 pages]
6.1 Processes and Programs
6.2 Process ID and Parent Process ID
6.3 Memory Layout of a Process
6.4 Virtual Memory Management
6.5 The Stack and Stack Frames
6.6 Command-line Arguments (argc, argv)
6.7 Environment List
6.8 Performing a Nonlocal Goto: setjmp() and longjmp()
6.9 Summary
6.10 Exercises

7 Memory Allocation [~15 pages]
7.1 Allocating Memory on the Heap
        7.1.1 Adjusting the Program Break: brk() and sbrk()
        7.1.2 Allocating Memory on the Heap: malloc() and free()
        7.1.3 Implementation of malloc() and free()
        7.1.4 Other Methods of Allocating Memory on the Heap
7.2 Allocating Memory on the Stack: alloca()
7.3 Summary
7.4 Exercises

8 Users and Groups [~15 pages]
8.1 The Password File: /etc/passwd
8.2 The Shadow Password File: /etc/shadow
8.3 The Group File: /etc/group
8.4 Retrieving User and Group Information
8.5 Password Encryption and User Authentication
8.6 Summary
8.7 Exercises

9 Process Credentials [~20 pages]
9.1 Real User ID and Real Group ID
9.2 Effective User ID and Effective Group ID
9.3 Set-user-ID and Set-group-ID Programs
9.4 Saved Set-user-ID and Saved Set-group-ID
9.5 File System User ID and File System Group ID
9.6 Supplementary Group IDs
9.7 Retrieving and Modifying Process Credentials
        9.7.1 Retrieving and Modifying Real, Effective, and Saved Set IDs
        9.7.2 Retrieving and Modifying File System IDs
        9.7.3 Retrieving and Modifying Supplementary Group IDs
        9.7.4 Summary of Calls for Modifying Process Credentials
        9.7.5 Example: Displaying Process Credentials
9.8 Summary
9.9 Exercises

10 Times and Dates [~25 pages]
10.1 Calendar Time
10.2 Time-Conversion Functions
        10.2.1 Converting time_t to Printable Form
        10.2.2 Converting Between time_t and Broken-down Time
        10.2.3 Converting Between Broken-down Time and Printable Form
10.3 Timezones
10.4 Locales
10.5 Updating the System Clock
10.6 The Software Clock (Jiffies)
10.7 Process Time
10.8 Summary
10.9 Exercises

11 System Limits and Options [~10 pages]
11.1 System Limits
11.2 Retrieving System Limits (and Options) at Run Time
11.3 Retrieving File-related Limits (and Options) at Run Time
11.4 Indeterminate Limits
11.5 System Options
11.6 Summary
11.7 Exercises

12 System and Process Information [~10 pages]
12.1 The /proc File System
        12.1.1 Obtaining Information about a Process: /proc/PID
        12.1.2 System Information under /proc
        12.1.3 Accessing /proc Files
12.2 System Identification: uname()
12.3 Summary
12.4 Exercises

13 File I/O Buffering [~20 pages]
13.1 Kernel Buffering of File I/O: The Buffer Cache
13.2 Buffering in the stdio Library
13.3 Controlling Kernel Buffering of File I/O
13.4 Summary of I/O Buffering
13.5 Giving the Kernel Hints about I/O Patterns: posix_fadvise()
13.6 Bypassing the Buffer Cache: Direct I/O
13.7 Mixing Library Functions and System Calls for File I/O
13.8 Summary
13.9 Exercises

14 File Systems [~30 pages]
14.1 Device Special Files (Devices)
14.2 Disks and Partitions
14.3 File Systems
14.4 I-nodes
14.5 The Virtual File System (VFS)
14.6 Journaling File Systems
14.7 Single Directory Hierarchy and Mount Points
14.8 Mounting and Unmounting File Systems
14.8.1 Mounting a File System: mount()
14.8.2 Unmounting a File System: umount() and umount2()
14.9 Advanced Mount Features
14.9.1 Mounting a File System at Multiple Mount Points
14.9.2 Stacking Multiple Mounts on the Same Mount Point
14.9.3 Mount Flags That Are Per-mount Options
14.9.4 Bind Mounts
14.9.5 Recursive Bind Mounts
14.10 A Virtual Memory File System: tmpfs
14.11 Obtaining Information about a File System: statvfs()
14.12 Summary
14.13 Exercises

15 File Attributes [~30 pages]
15.1 Retrieving File Information: stat()
15.2 File Timestamps
        15.2.1 Changing File Timestamps with utime() and utimes()
        15.2.2 Changing File Timestamps with utimensat() and futimens()
15.3 File Ownership
        15.3.1 Ownership of New Files
        15.3.2 Changing File Ownership: chown(), fchown(), and lchown()
15.4 File Permissions
        15.4.1 Permissions on Regular Files
        15.4.2 Permissions on Directories
        15.4.3 Permission Checking Algorithm
        15.4.4 Checking File Accessibility: access()
        15.4.5 Set-user-ID, Set-group-ID, and Sticky Bits
        15.4.6 The Process File Mode Creation Mask: umask()
        15.4.7 Changing File Permissions: chmod() and fchmod()
15.5 I-node Flags (ext2 Extended File Attributes)
15.6 Summary
15.7 Exercises

16 Extended Attributes [~8 pages]
16.1 Overview
16.2 Extended Attribute Implementation Details
16.3 System Calls for Manipulating Extended Attributes
16.4 Summary
16.5 Exercises

17 Access Control Lists [~20 pages]
17.1 Overview
17.2 ACL Permission-Checking Algorithm
17.3 Long and Short Text Forms for ACLs
17.4 The ACL_MASK Entry and the ACL Group Class
17.5 The getfacl and setfacl Commands
17.6 Default ACLs and File Creation
17.7 ACL Implementation Limits
17.8 The ACL API
17.9 Summary
17.10 Exercises

18 Directories and Links [~35 pages]
18.1 Directories and (Hard) Links
18.2 Symbolic (Soft) Links
18.3 Creating and Removing (Hard) Links: link() and unlink()
18.4 Changing the Name of a File: rename()
18.5 Working with Symbolic Links: symlink() and readlink()
18.6 Creating and Removing Directories: mkdir() and rmdir()
18.7 Removing a File or Directory: remove()
18.8 Reading Directories: opendir() and readdir()
18.9 File Tree Walking: nftw()
18.10 The Current Working Directory of a Process
18.11 Operating Relative to a Directory File Descriptor
18.12 Changing the Root Directory of a Process: chroot()
18.13 Resolving a Pathname: realpath()
18.14 Parsing Pathname Strings: dirname() and basename()
18.15 Summary
18.16 Exercises

19 Monitoring File Events [~12 pages]
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

20 Signals: Fundamental Concepts [~30 pages]
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

21 Signals: Signal Handlers [~25 pages]
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

22 Signals: Advanced Features [~30 pages]
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

23 Timers and Sleeping [~30 pages]
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

24 Process Creation [~20 pages]
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

25 Process Termination [~10 pages]
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

26 Monitoring Child Processes [~20 pages]
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

27 Program Execution [~20 pages]
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

28 Process Creation and Program Execution in More Detail [~25 pages]
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

29 Threads: Introduction [~15 pages]
29.1 Overview
29.2 Background Details of the Pthreads API
29.3 Thread Creation
29.4 Thread Termination
29.5 Thread IDs
29.6 Joining with a Terminated Thread: pthread_join()
29.7 Detaching a Thread: pthread_detach()
29.8 Thread Attributes
29.9 Threads Versus Processes
29.10 Summary
29.11 Exercises


30 Threads: Thread Synchronization [~25 pages]
30.1 Protecting Accesses to Shared Variables: Mutexes
        30.1.1 Statically Allocated Mutexes
        30.1.2 Locking and Unlocking a Mutex
        30.1.3 Performance of Mutexes
        30.1.4 Mutex Deadlocks
        30.1.5 Dynamically Initializing a Mutex
        30.1.6 Mutex Attributes
        30.1.7 Mutex Types
30.2 Signaling Changes of State: Condition Variables
        30.2.1 Statically Allocated Condition Variables
        30.2.2 Signaling and Waiting on Condition Variables
        30.2.3 Testing a Condition Variable’s Predicate
        30.2.4 Example Program: Joining Any Terminated Thread
        30.2.5 Dynamically Allocated Condition Variables
30.3 Summary
30.4 Exercises

31 Threads: Thread Safety and Per-thread Storage [~15 pages]
31.1 Thread Safety (and Reentrancy Revisited)
31.2 One-time Initialization
31.3 Thread-specific Data
        31.3.1 Thread-specific Data from the Library Function’s Perspective
        31.3.2 Overview of the Thread-specific Data API
        31.3.3 Details of the Thread-specific Data API
        31.3.4 Employing the Thread-specific Data API
        31.3.5 Thread-specific Data Implementation Limits
31.4 Thread-local Storage
31.5 Summary
31.6 Exercises

32 Threads: Thread Cancellation [~10 pages]
32.1 Canceling a Thread
32.2 Cancellation State and Type
32.3 Cancellation Points
32.4 Testing for Thread Cancellation
32.5 Cleanup Handlers
32.6 Asynchronous Cancelability
32.7 Summary
32.8 Exercises

33 Threads: Further Details [~15 pages]
33.1 Thread Stacks
33.2 Threads and Signals
        33.2.1 How the Unix Signal Model Maps to Threads
        33.2.2 Manipulating the Thread Signal Mask
        33.2.3 Sending a Signal to a Thread
        33.2.4 Dealing with Asynchronous Signals Sanely
33.3 Threads and Process Control
33.4 Thread Implementation Models
33.5 Linux Implementations of POSIX Threads
        33.5.1 LinuxThreads
        33.5.2 NPTL
        33.5.3 Which Threading Implementation?
33.6 Advanced Features of the Pthreads API
33.7 Summary
33.8 Exercises

2009-09-04

Chapter 33: Threads: Further Details

This chapter provides further details on various aspects of POSIX threads. We discuss the interaction of threads with aspects of the traditional Unix API; in particular, signals and the process control primitives (fork(), exec(), and _exit()). We also provide an overview of the two POSIX threads implementations available on Linux--LinuxThreads and NPTL--and discuss where each of these implementations deviates from the SUSv3 specification of Pthreads.

33 Threads: Further Details
33.1 Thread Stacks
33.2 Threads and Signals
        33.2.1 How the Unix Signal Model Maps to Threads
        33.2.2 Manipulating the Thread Signal Mask
        33.2.3 Sending a Signal to a Thread
        33.2.4 Dealing with Asynchronous Signals Sanely
33.3 Threads and Process Control
33.4 Thread Implementation Models
33.5 Linux Implementations of POSIX Threads
        33.5.1 LinuxThreads
        33.5.2 NPTL
        33.5.3 Which Threading Implementation?
33.6 Advanced Features of the Pthreads API
33.7 Summary
33.8 Exercises

2009-09-03

Chapter 32: Threads: Thread Cancellation

Typically, multiple threads execute in parallel, with each thread performing its task until it decides to terminate by calling pthread_exit() or returning from the thread’s start function.

Sometimes, it can be useful to cancel a thread; that is, to send it a request asking it to terminate now. This could be useful, for example, if a group of threads is performing a calculation, and one thread detects an error condition that requires the other threads to terminate. Alternatively, a GUI-driven application may provide a cancel button to allow the user to terminate a task that is being performed by a thread in the background; in this case, the main thread (controlling the GUI) needs to tell the background thread to terminate.

In this chapter, we describe the POSIX threads cancellation mechanism.

32 Threads: Thread Cancellation
32.1 Canceling a Thread
32.2 Cancellation State and Type
32.3 Cancellation Points
32.4 Testing for Thread Cancellation
32.5 Cleanup Handlers
32.6 Asynchronous Cancelability
32.7 Summary
32.8 Exercises

2009-09-02

Chapter 31: Threads: Thread Safety and Per-thread Storage

This chapter continues the discussion of the POSIX threads API. It covers thread-safe functions and one-time initialization. We also discuss how to use thread-specific data or thread-local storage to make an existing function thread-safe without changing the function's interface.

31 Threads: Thread Safety and Per-thread Storage
31.1 Thread Safety (and Reentrancy Revisited)
31.2 One-time Initialization
31.3 Thread-specific Data
        31.3.1 Thread-specific Data from the Library Function’s Perspective
        31.3.2 Overview of the Thread-specific Data API
        31.3.3 Details of the Thread-specific Data API
        31.3.4 Employing the Thread-specific Data API
        31.3.5 Thread-specific Data Implementation Limits
31.4 Thread-local Storage
31.5 Summary
31.6 Exercises

2009-09-01

Chapter 30: Threads: Thread Synchronization

In this chapter, we describe two tools that threads can use to synchronize their actions: mutexes and condition variables. Mutexes allow threads to synchronize their use of a shared resource, so that, for example, one thread doesn't try to access a shared variable at the same time as another thread is modifying it. Condition variables perform a complementary task: They allow threads to inform each other that a shared variable (or other shared resource) has changed state.

30 Threads: Thread Synchronization
30.1 Protecting Accesses to Shared Variables: Mutexes
        30.1.1 Statically Allocated Mutexes
        30.1.2 Locking and Unlocking a Mutex
        30.1.3 Performance of Mutexes
        30.1.4 Mutex Deadlocks
        30.1.5 Dynamically Initializing a Mutex
        30.1.6 Mutex Attributes
        30.1.7 Mutex Types
30.2 Signaling Changes of State: Condition Variables
        30.2.1 Statically Allocated Condition Variables
        30.2.2 Signaling and Waiting on Condition Variables
        30.2.3 Testing a Condition Variable’s Predicate
        30.2.4 Example Program: Joining Any Terminated Thread
        30.2.5 Dynamically Allocated Condition Variables
30.3 Summary
30.4 Exercises

Chapters 38, 39, and 40 are in copyedit

Chapter 37 came back from coyedit. Chapters 38, 39, and 40 are now in copyedit.