The Linux Programming Interface

Book description

The Linux Programming Interface is the definitive guide to the Linux and UNIX programming interface—the interface employed by nearly every application that runs on a Linux or UNIX system.

In this authoritative work, Linux programming expert Michael Kerrisk provides detailed descriptions of the system calls and library functions that you need in order to master the craft of system programming, and accompanies his explanations with clear, complete example programs.

You'll find descriptions of over 500 system calls and library functions, and more than 200 example programs, 88 tables, and 115 diagrams. You'll learn how to:

  • Read and write files efficiently
  • Use signals, clocks, and timers
  • Create processes and execute programs
  • Write secure programs
  • Write multithreaded programs using POSIX threads
  • Build and use shared libraries
  • Perform interprocess communication using pipes, message queues, shared memory, and semaphores
  • Write network applications with the sockets API

While The Linux Programming Interface covers a wealth of Linux-specific features, including epoll, inotify, and the /proc file system, its emphasis on UNIX standards (POSIX.1-2001/SUSv3 and POSIX.1-2008/SUSv4) makes it equally valuable to programmers working on other UNIX platforms.

The Linux Programming Interface is the most comprehensive single-volume work on the Linux and UNIX programming interface, and a book that's destined to become a new classic.

Praise for The Linux Programming Interface "If I had to choose a single book to sit next to my machine when writing software for Linux, this would be it." —Martin Landers, Software Engineer, Google "This book, with its detailed descriptions and examples, contains everything you need to understand the details and nuances of the low-level programming APIs in Linux . . . no matter what the level of reader, there will be something to be learnt from this book." —Mel Gorman, Author of Understanding the Linux Virtual Memory Manager "Michael Kerrisk has not only written a great book about Linux programming and how it relates to various standards, but has also taken care that bugs he noticed got fixed and the man pages were (greatly) improved. In all three ways, he has made Linux programming easier. The in-depth treatment of topics in The Linux Programming Interface . . . makes it a must-have reference for both new and experienced Linux programmers." —Andreas Jaeger, Program Manager, openSUSE, Novell "Michael's inexhaustible determination to get his information right, and to express it clearly and concisely, has resulted in a strong reference source for programmers. While this work is targeted at Linux programmers, it will be of value to any programmer working in the UNIX/POSIX ecosystem." —David Butenhof, Author of Programming with POSIX Threads and Contributor to the POSIX and UNIX Standards ". . . a very thorough—yet easy to read—explanation of UNIX system and network programming, with an emphasis on Linux systems. It's certainly a book I'd recommend to anybody wanting to get into UNIX programming (in general) or to experienced UNIX programmers wanting to know 'what's new' in the popular GNU/Linux system." —Fernando Gont, Network Security Researcher, IETF Participant, and RFC Author ". . . encyclopedic in the breadth and depth of its coverage, and textbook-like in its wealth of worked examples and exercises. Each topic is clearly and comprehensively covered, from theory to hands-on working code. Professionals, students, educators, this is the Linux/UNIX reference that you have been waiting for." —Anthony Robins, Associate Professor of Computer Science, The University of Otago "I've been very impressed by the precision, the quality and the level of detail Michael Kerrisk put in his book. He is a great expert of Linux system calls and lets us share his knowledge and understanding of the Linux APIs." —Christophe Blaess, Author of Programmation systeme en C sous Linux ". . . an essential resource for the serious or professional Linux and UNIX systems programmer. Michael Kerrisk covers the use of all the key APIs across both the Linux and UNIX system interfaces with clear descriptions and tutorial examples and stresses the importance and benefits of following standards such as the Single UNIX Specification and POSIX 1003.1." —Andrew Josey, Director, Standards, The Open Group, and Chair of the POSIX 1003.1 Working Group "What could be better than an encyclopedic reference to the Linux system, from the standpoint of the system programmer, written by none other than the maintainer of the man pages himself? The Linux Programming Interface is comprehensive and detailed. I firmly expect it to become an indispensable addition to my programming bookshelf." —Bill Gallmeister, Author of POSIX.4 Programmer's Guide: Programming for the Real World ". . . the most complete and up-to-date book about Linux and UNIX system programming. If you're new to Linux system programming, if you're a UNIX veteran focused on portability while interested in learning the Linux way, or if you're simply looking for an excellent reference about the Linux programming interface, then Michael Kerrisk's book is definitely the companion you want on your bookshelf." —Loic Domaigne, Chief Software Architect (Embedded), Corpuls.com

Publisher resources

View/Submit Errata

Table of contents

  1. Cover
  2. Title Page
  3. Copyright Page
  4. Brief Contents
  5. Contents in Detail
  6. Preface
  7. Chapter 1: History and Standards
    1. 1.1 A Brief History of UNIX and C
    2. 1.2 A Brief History of Linux
      1. 1.2.1 The GNU Project
      2. 1.2.2 The Linux Kernel
    3. 1.3 Standardization
      1. 1.3.1 The C Programming Language
      2. 1.3.2 The First POSIX Standards
      3. 1.3.3 X/Open Company and The Open Group
      4. 1.3.4 SUSv3 and POSIX.1-2001
      5. 1.3.5 SUSv4 and POSIX.1-2008
      6. 1.3.6 UNIX Standards Timeline
      7. 1.3.7 Implementation Standards
      8. 1.3.8 Linux, Standards, and the Linux Standard Base
    4. 1.4 Summary
  8. Chapter 2: Fundamental Concepts
    1. 2.1 The Core Operating System: The Kernel
    2. 2.2 The Shell
    3. 2.3 Users and Groups
    4. 2.4 Single Directory Hierarchy, Directories, Links, and Files
    5. 2.5 File I/O Model
    6. 2.6 Programs
    7. 2.7 Processes
    8. 2.8 Memory Mappings
    9. 2.9 Static and Shared Libraries
    10. 2.10 Interprocess Communication and Synchronization
    11. 2.11 Signals
    12. 2.12 Threads
    13. 2.13 Process Groups and Shell Job Control
    14. 2.14 Sessions, Controlling Terminals, and Controlling Processes
    15. 2.15 Pseudoterminals
    16. 2.16 Date and Time
    17. 2.17 Client-Server Architecture
    18. 2.18 Realtime
    19. 2.19 The /proc File System
    20. 2.20 Summary
  9. Chapter 3: System Programming Concepts
    1. 3.1 System Calls
    2. 3.2 Library Functions
    3. 3.3 The Standard C Library; The GNU C Library (glibc)
    4. 3.4 Handling Errors from System Calls and Library Functions
    5. 3.5 Notes on the Example Programs in This Book
      1. 3.5.1 Command-Line Options and Arguments
      2. 3.5.2 Common Functions and Header Files
    6. 3.6 Portability Issues
      1. 3.6.1 Feature Test Macros
      2. 3.6.2 System Data Types
      3. 3.6.3 Miscellaneous Portability Issues
    7. 3.7 Summary
    8. 3.8 Exercise
  10. Chapter 4: File I/O: The Universal I/O Model
    1. 4.1 Overview
    2. 4.2 Universality of I/O
    3. 4.3 Opening a File: open()
      1. 4.3.1 The open() flags Argument
      2. 4.3.2 Errors from open()
      3. 4.3.3 The creat() System Call
    4. 4.4 Reading from a File: read()
    5. 4.5 Writing to a File: write()
    6. 4.6 Closing a File: close()
    7. 4.7 Changing the File Offset: lseek()
    8. 4.8 Operations Outside the Universal I/O Model: ioctl()
    9. 4.9 Summary
    10. 4.10 Exercises
  11. Chapter 5: File I/O: Further Details
    1. 5.1 Atomicity and Race Conditions
    2. 5.2 File Control Operations: fcntl()
    3. 5.3 Open File Status Flags
    4. 5.4 Relationship Between File Descriptors and Open Files
    5. 5.5 Duplicating File Descriptors
    6. 5.6 File I/O at a Specified Offset: pread() and pwrite()
    7. 5.7 Scatter-Gather I/O: readv() and writev()
    8. 5.8 Truncating a File: truncate() and ftruncate()
    9. 5.9 Nonblocking I/O
    10. 5.10 I/O on Large Files
    11. 5.11 The /dev/fd Directory
    12. 5.12 Creating Temporary Files
    13. 5.13 Summary
    14. 5.14 Exercises
  12. Chapter 6: Processes
    1. 6.1 Processes and Programs
    2. 6.2 Process ID and Parent Process ID
    3. 6.3 Memory Layout of a Process
    4. 6.4 Virtual Memory Management
    5. 6.5 The Stack and Stack Frames
    6. 6.6 Command-Line Arguments (argc, argv)
    7. 6.7 Environment List
    8. 6.8 Performing a Nonlocal Goto: setjmp() and longjmp()
    9. 6.9 Summary
    10. 6.10 Exercises
  13. Chapter 7: Memory Allocation
    1. 7.1 Allocating Memory on the Heap
      1. 7.1.1 Adjusting the Program Break: brk() and sbrk()
      2. 7.1.2 Allocating Memory on the Heap: malloc() and free()
      3. 7.1.3 Implementation of malloc() and free()
      4. 7.1.4 Other Methods of Allocating Memory on the Heap
    2. 7.2 Allocating Memory on the Stack: alloca()
    3. 7.3 Summary
    4. 7.4 Exercises
  14. Chapter 8: Users and Groups
    1. 8.1 The Password File: /etc/passwd
    2. 8.2 The Shadow Password File: /etc/shadow
    3. 8.3 The Group File: /etc/group
    4. 8.4 Retrieving User and Group Information
    5. 8.5 Password Encryption and User Authentication
    6. 8.6 Summary
    7. 8.7 Exercises
  15. Chapter 9: Process Credentials
    1. 9.1 Real User ID and Real Group ID
    2. 9.2 Effective User ID and Effective Group ID
    3. 9.3 Set-User-ID and Set-Group-ID Programs
    4. 9.4 Saved Set-User-ID and Saved Set-Group-ID
    5. 9.5 File-System User ID and File-System Group ID
    6. 9.6 Supplementary Group IDs
    7. 9.7 Retrieving and Modifying Process Credentials
      1. 9.7.1 Retrieving and Modifying Real, Effective, and Saved Set IDs
      2. 9.7.2 Retrieving and Modifying File-System IDs
      3. 9.7.3 Retrieving and Modifying Supplementary Group IDs
      4. 9.7.4 Summary of Calls for Modifying Process Credentials
      5. 9.7.5 Example: Displaying Process Credentials
    8. 9.8 Summary
    9. 9.9 Exercises
  16. Chapter 10: Time
    1. 10.1 Calendar Time
    2. 10.2 Time-Conversion Functions
      1. 10.2.1 Converting time_t to Printable Form
      2. 10.2.2 Converting Between time_t and Broken-Down Time
      3. 10.2.3 Converting Between Broken-Down Time and Printable Form
    3. 10.3 Timezones
    4. 10.4 Locales
    5. 10.5 Updating the System Clock
    6. 10.6 The Software Clock (Jiffies)
    7. 10.7 Process Time
    8. 10.8 Summary
    9. 10.9 Exercise
  17. Chapter 11: System Limits and Options
    1. 11.1 System Limits
    2. 11.2 Retrieving System Limits (and Options) at Run Time
    3. 11.3 Retrieving File-Related Limits (and Options) at Run Time
    4. 11.4 Indeterminate Limits
    5. 11.5 System Options
    6. 11.6 Summary
    7. 11.7 Exercises
  18. Chapter 12: System and Process Information
    1. 12.1 The /proc File System
      1. 12.1.1 Obtaining Information About a Process: /proc/PID
      2. 12.1.2 System Information Under /proc
      3. 12.1.3 Accessing /proc Files
    2. 12.2 System Identification: uname()
    3. 12.3 Summary
    4. 12.4 Exercises
  19. Chapter 13: File I/O Buffering
    1. 13.1 Kernel Buffering of File I/O: The Buffer Cache
    2. 13.2 Buffering in the stdio Library
    3. 13.3 Controlling Kernel Buffering of File I/O
    4. 13.4 Summary of I/O Buffering
    5. 13.5 Advising the Kernel About I/O Patterns
    6. 13.6 Bypassing the Buffer Cache: Direct I/O
    7. 13.7 Mixing Library Functions and System Calls for File I/O
    8. 13.8 Summary
    9. 13.9 Exercises
  20. Chapter 14: File Systems
    1. 14.1 Device Special Files (Devices)
    2. 14.2 Disks and Partitions
    3. 14.3 File Systems
    4. 14.4 I-nodes
    5. 14.5 The Virtual File System (VFS)
    6. 14.6 Journaling File Systems
    7. 14.7 Single Directory Hierarchy and Mount Points
    8. 14.8 Mounting and Unmounting File Systems
      1. 14.8.1 Mounting a File System: mount()
      2. 14.8.2 Unmounting a File System: umount() and umount2()
    9. 14.9 Advanced Mount Features
      1. 14.9.1 Mounting a File System at Multiple Mount Points
      2. 14.9.2 Stacking Multiple Mounts on the Same Mount Point
      3. 14.9.3 Mount Flags That Are Per-Mount Options
      4. 14.9.4 Bind Mounts
      5. 14.9.5 Recursive Bind Mounts
    10. 14.10 A Virtual Memory File System: tmpfs
    11. 14.11 Obtaining Information About a File System: statvfs()
    12. 14.12 Summary
    13. 14.13 Exercise
  21. Chapter 15: File Attributes
    1. 15.1 Retrieving File Information: stat()
    2. 15.2 File Timestamps
      1. 15.2.1 Changing File Timestamps with utime() and utimes()
      2. 15.2.2 Changing File Timestamps with utimensat() and futimens()
    3. 15.3 File Ownership
      1. 15.3.1 Ownership of New Files
      2. 15.3.2 Changing File Ownership: chown(), fchown(), and lchown()
    4. 15.4 File Permissions
      1. 15.4.1 Permissions on Regular Files
      2. 15.4.2 Permissions on Directories
      3. 15.4.3 Permission-Checking Algorithm
      4. 15.4.4 Checking File Accessibility: access()
      5. 15.4.5 Set-User-ID, Set-Group-ID, and Sticky Bits
      6. 15.4.6 The Process File Mode Creation Mask: umask()
      7. 15.4.7 Changing File Permissions: chmod() and fchmod()
    5. 15.5 I-node Flags (ext2 Extended File Attributes)
    6. 15.6 Summary
    7. 15.7 Exercises
  22. Chapter 16: Extended Attributes
    1. 16.1 Overview
    2. 16.2 Extended Attribute Implementation Details
    3. 16.3 System Calls for Manipulating Extended Attributes
    4. 16.4 Summary
    5. 16.5 Exercise
  23. Chapter 17: Access Control Lists
    1. 17.1 Overview
    2. 17.2 ACL Permission-Checking Algorithm
    3. 17.3 Long and Short Text Forms for ACLs
    4. 17.4 The ACL_MASK Entry and the ACL Group Class
    5. 17.5 The getfacl and setfacl Commands
    6. 17.6 Default ACLs and File Creation
    7. 17.7 ACL Implementation Limits
    8. 17.8 The ACL API
    9. 17.9 Summary
    10. 17.10 Exercise
  24. Chapter 18: Directories and Links
    1. 18.1 Directories and (Hard) Links
    2. 18.2 Symbolic (Soft) Links
    3. 18.3 Creating and Removing (Hard) Links: link() and unlink()
    4. 18.4 Changing the Name of a File: rename()
    5. 18.5 Working with Symbolic Links: symlink() and readlink()
    6. 18.6 Creating and Removing Directories: mkdir() and rmdir()
    7. 18.7 Removing a File or Directory: remove()
    8. 18.8 Reading Directories: opendir() and readdir()
    9. 18.9 File Tree Walking: nftw()
    10. 18.10 The Current Working Directory of a Process
    11. 18.11 Operating Relative to a Directory File Descriptor
    12. 18.12 Changing the Root Directory of a Process: chroot()
    13. 18.13 Resolving a Pathname: realpath()
    14. 18.14 Parsing Pathname Strings: dirname() and basename()
    15. 18.15 Summary
    16. 18.16 Exercises
  25. Chapter 19: Monitoring File Events
    1. 19.1 Overview
    2. 19.2 The inotify API
    3. 19.3 inotify Events
    4. 19.4 Reading inotify Events
    5. 19.5 Queue Limits and /proc Files
    6. 19.6 An Older System for Monitoring File Events: dnotify
    7. 19.7 Summary
    8. 19.8 Exercise
  26. Chapter 20: Signals: Fundamental Concepts
    1. 20.1 Concepts and Overview
    2. 20.2 Signal Types and Default Actions
    3. 20.3 Changing Signal Dispositions: signal()
    4. 20.4 Introduction to Signal Handlers
    5. 20.5 Sending Signals: kill()
    6. 20.6 Checking for the Existence of a Process
    7. 20.7 Other Ways of Sending Signals: raise() and killpg()
    8. 20.8 Displaying Signal Descriptions
    9. 20.9 Signal Sets
    10. 20.10 The Signal Mask (Blocking Signal Delivery)
    11. 20.11 Pending Signals
    12. 20.12 Signals Are Not Queued
    13. 20.13 Changing Signal Dispositions: sigaction()
    14. 20.14 Waiting for a Signal: pause()
    15. 20.15 Summary
    16. 20.16 Exercises
  27. Chapter 21: Signals: Signal Handlers
    1. 21.1 Designing Signal Handlers
      1. 21.1.1 Signals Are Not Queued (Revisited)
      2. 21.1.2 Reentrant and Async-Signal-Safe Functions
      3. 21.1.3 Global Variables and the sig_atomic_t Data Type
    2. 21.2 Other Methods of Terminating a Signal Handler
      1. 21.2.1 Performing a Nonlocal Goto from a Signal Handler
      2. 21.2.2 Terminating a Process Abnormally: abort()
    3. 21.3 Handling a Signal on an Alternate Stack: sigaltstack()
    4. 21.4 The SA_SIGINFO Flag
    5. 21.5 Interruption and Restarting of System Calls
    6. 21.6 Summary
    7. 21.7 Exercise
  28. Chapter 22: Signals: Advanced Features
    1. 22.1 Core Dump Files
    2. 22.2 Special Cases for Delivery, Disposition, and Handling
    3. 22.3 Interruptible and Uninterruptible Process Sleep States
    4. 22.4 Hardware-Generated Signals
    5. 22.5 Synchronous and Asynchronous Signal Generation
    6. 22.6 Timing and Order of Signal Delivery
    7. 22.7 Implementation and Portability of signal()
    8. 22.8 Realtime Signals
      1. 22.8.1 Sending Realtime Signals
      2. 22.8.2 Handling Realtime Signals
    9. 22.9 Waiting for a Signal Using a Mask: sigsuspend()
    10. 22.10 Synchronously Waiting for a Signal
    11. 22.11 Fetching Signals via a File Descriptor
    12. 22.12 Interprocess Communication with Signals
    13. 22.13 Earlier Signal APIs (System V and BSD)
    14. 22.14 Summary
    15. 22.15 Exercises
  29. Chapter 23: Timers and Sleeping
    1. 23.1 Interval Timers
    2. 23.2 Scheduling and Accuracy of Timers
    3. 23.3 Setting Timeouts on Blocking Operations
    4. 23.4 Suspending Execution for a Fixed Interval (Sleeping)
      1. 23.4.1 Low-Resolution Sleeping: sleep()
      2. 23.4.2 High-Resolution Sleeping: nanosleep()
    5. 23.5 POSIX Clocks
      1. 23.5.1 Retrieving the Value of a Clock: clock_gettime()
      2. 23.5.2 Setting the Value of a Clock: clock_settime()
      3. 23.5.3 Obtaining the Clock ID of a Specific Process or Thread
      4. 23.5.4 Improved High-Resolution Sleeping: clock_nanosleep()
    6. 23.6 POSIX Interval Timers
      1. 23.6.1 Creating a Timer: timer_create()
      2. 23.6.2 Arming and Disarming a Timer: timer_settime()
      3. 23.6.3 Retrieving the Current Value of a Timer: timer_gettime()
      4. 23.6.4 Deleting a Timer: timer_delete()
      5. 23.6.5 Notification via a Signal
      6. 23.6.6 Timer Overruns
      7. 23.6.7 Notification via a Thread
    7. 23.7 Timers That Notify via File Descriptors: The timerfd API
    8. 23.8 Summary
    9. 23.9 Exercises
  30. Chapter 24: Process Creation
    1. 24.1 Overview of fork(), exit(), wait(), and execve()
    2. 24.2 Creating a New Process: fork()
      1. 24.2.1 File Sharing Between Parent and Child
      2. 24.2.2 Memory Semantics of fork()
    3. 24.3 The vfork() System Call
    4. 24.4 Race Conditions After fork()
    5. 24.5 Avoiding Race Conditions by Synchronizing with Signals
    6. 24.6 Summary
    7. 24.7 Exercises
  31. Chapter 25: Process Termination
    1. 25.1 Terminating a Process: _exit() and exit()
    2. 25.2 Details of Process Termination
    3. 25.3 Exit Handlers
    4. 25.4 Interactions Between fork(), stdio Buffers, and _exit()
    5. 25.5 Summary
    6. 25.6 Exercise
  32. Chapter 26: Monitoring Child Processes
    1. 26.1 Waiting on a Child Process
      1. 26.1.1 The wait() System Call
      2. 26.1.2 The waitpid() System Call
      3. 26.1.3 The Wait Status Value
      4. 26.1.4 Process Termination from a Signal Handler
      5. 26.1.5 The waitid() System Call
      6. 26.1.6 The wait3() and wait4() System Calls
    2. 26.2 Orphans and Zombies
    3. 26.3 The SIGCHLD Signal
      1. 26.3.1 Establishing a Handler for SIGCHLD
      2. 26.3.2 Delivery of SIGCHLD for Stopped Children
      3. 26.3.3 Ignoring Dead Child Processes
    4. 26.4 Summary
    5. 26.5 Exercises
  33. Chapter 27: Program Execution
    1. 27.1 Executing a New Program: execve()
    2. 27.2 The exec() Library Functions
      1. 27.2.1 The PATH Environment Variable
      2. 27.2.2 Specifying Program Arguments as a List
      3. 27.2.3 Passing the Caller’s Environment to the New Program
      4. 27.2.4 Executing a File Referred to by a Descriptor: fexecve()
    3. 27.3 Interpreter Scripts
    4. 27.4 File Descriptors and exec()
    5. 27.5 Signals and exec()
    6. 27.6 Executing a Shell Command: system()
    7. 27.7 Implementing system()
    8. 27.8 Summary
    9. 27.9 Exercises
  34. Chapter 28: Process Creation and Program Execution in More Detail
    1. 28.1 Process Accounting
    2. 28.2 The clone() System Call
      1. 28.2.1 The clone() flags Argument
      2. 28.2.2 Extensions to waitpid() for Cloned Children
    3. 28.3 Speed of Process Creation
    4. 28.4 Effect of exec() and fork() on Process Attributes
    5. 28.5 Summary
    6. 28.6 Exercise
  35. Chapter 29: Threads: Introduction
    1. 29.1 Overview
    2. 29.2 Background Details of the Pthreads API
    3. 29.3 Thread Creation
    4. 29.4 Thread Termination
    5. 29.5 Thread IDs
    6. 29.6 Joining with a Terminated Thread
    7. 29.7 Detaching a Thread
    8. 29.8 Thread Attributes
    9. 29.9 Threads Versus Processes
    10. 29.10 Summary
    11. 29.11 Exercises
  36. Chapter 30: Threads: Thread Synchronization
    1. 30.1 Protecting Accesses to Shared Variables: Mutexes
      1. 30.1.1 Statically Allocated Mutexes
      2. 30.1.2 Locking and Unlocking a Mutex
      3. 30.1.3 Performance of Mutexes
      4. 30.1.4 Mutex Deadlocks
      5. 30.1.5 Dynamically Initializing a Mutex
      6. 30.1.6 Mutex Attributes
      7. 30.1.7 Mutex Types
    2. 30.2 Signaling Changes of State: Condition Variables
      1. 30.2.1 Statically Allocated Condition Variables
      2. 30.2.2 Signaling and Waiting on Condition Variables
      3. 30.2.3 Testing a Condition Variable’s Predicate
      4. 30.2.4 Example Program: Joining Any Terminated Thread
      5. 30.2.5 Dynamically Allocated Condition Variables
    3. 30.3 Summary
    4. 30.4 Exercises
  37. Chapter 31: Threads: Thread Safety and Per-Thread Storage
    1. 31.1 Thread Safety (and Reentrancy Revisited)
    2. 31.2 One-Time Initialization
    3. 31.3 Thread-Specific Data
      1. 31.3.1 Thread-Specific Data from the Library Function’s Perspective
      2. 31.3.2 Overview of the Thread-Specific Data API
      3. 31.3.3 Details of the Thread-Specific Data API
      4. 31.3.4 Employing the Thread-Specific Data API
      5. 31.3.5 Thread-Specific Data Implementation Limits
    4. 31.4 Thread-Local Storage
    5. 31.5 Summary
    6. 31.6 Exercises
  38. Chapter 32: Threads: Thread Cancellation
    1. 32.1 Canceling a Thread
    2. 32.2 Cancellation State and Type
    3. 32.3 Cancellation Points
    4. 32.4 Testing for Thread Cancellation
    5. 32.5 Cleanup Handlers
    6. 32.6 Asynchronous Cancelability
    7. 32.7 Summary
  39. Chapter 33: Threads: Further Details
    1. 33.1 Thread Stacks
    2. 33.2 Threads and Signals
      1. 33.2.1 How the UNIX Signal Model Maps to Threads
      2. 33.2.2 Manipulating the Thread Signal Mask
      3. 33.2.3 Sending a Signal to a Thread
      4. 33.2.4 Dealing with Asynchronous Signals Sanely
    3. 33.3 Threads and Process Control
    4. 33.4 Thread Implementation Models
    5. 33.5 Linux Implementations of POSIX Threads
      1. 33.5.1 LinuxThreads
      2. 33.5.2 NPTL
      3. 33.5.3 Which Threading Implementation?
    6. 33.6 Advanced Features of the Pthreads API
    7. 33.7 Summary
    8. 33.8 Exercises
  40. Chapter 34: Process Groups, Sessions, and Job Control
    1. 34.1 Overview
    2. 34.2 Process Groups
    3. 34.3 Sessions
    4. 34.4 Controlling Terminals and Controlling Processes
    5. 34.5 Foreground and Background Process Groups
    6. 34.6 The SIGHUP Signal
      1. 34.6.1 Handling of SIGHUP by the Shell
      2. 34.6.2 SIGHUP and Termination of the Controlling Process
    7. 34.7 Job Control
      1. 34.7.1 Using Job Control Within the Shell
      2. 34.7.2 Implementing Job Control
      3. 34.7.3 Handling Job-Control Signals
      4. 34.7.4 Orphaned Process Groups (and SIGHUP Revisited)
    8. 34.8 Summary
    9. 34.9 Exercises
  41. Chapter 35: Process Priorities and Scheduling
    1. 35.1 Process Priorities (Nice Values)
    2. 35.2 Overview of Realtime Process Scheduling
      1. 35.2.1 The SCHED_RR Policy
      2. 35.2.2 The SCHED_FIFO Policy
      3. 35.2.3 The SCHED_BATCH and SCHED_IDLE Policies
    3. 35.3 Realtime Process Scheduling API
      1. 35.3.1 Realtime Priority Ranges
      2. 35.3.2 Modifying and Retrieving Policies and Priorities
      3. 35.3.3 Relinquishing the CPU
      4. 35.3.4 The SCHED_RR Time Slice
    4. 35.4 CPU Affinity
    5. 35.5 Summary
    6. 35.6 Exercises
  42. Chapter 36: Process Resources
    1. 36.1 Process Resource Usage
    2. 36.2 Process Resource Limits
    3. 36.3 Details of Specific Resource Limits
    4. 36.4 Summary
    5. 36.5 Exercises
  43. Chapter 37: Daemons
    1. 37.1 Overview
    2. 37.2 Creating a Daemon
    3. 37.3 Guidelines for Writing Daemons
    4. 37.4 Using SIGHUP to Reinitialize a Daemon
    5. 37.5 Logging Messages and Errors Using syslog
      1. 37.5.1 Overview
      2. 37.5.2 The syslog API
      3. 37.5.3 The /etc/syslog.conf File
    6. 37.6 Summary
    7. 37.7 Exercise
  44. Chapter 38: Writing Secure Privileged Programs
    1. 38.1 Is a Set-User-ID or Set-Group-ID Program Required?
    2. 38.2 Operate with Least Privilege
    3. 38.3 Be Careful When Executing a Program
    4. 38.4 Avoid Exposing Sensitive Information
    5. 38.5 Confine the Process
    6. 38.6 Beware of Signals and Race Conditions
    7. 38.7 Pitfalls When Performing File Operations and File I/O
    8. 38.8 Don’t Trust Inputs or the Environment
    9. 38.9 Beware of Buffer Overruns
    10. 38.10 Beware of Denial-of-Service Attacks
    11. 38.11 Check Return Statuses and Fail Safely
    12. 38.12 Summary
    13. 38.13 Exercises
  45. Chapter 39: Capabilities
    1. 39.1 Rationale for Capabilities
    2. 39.2 The Linux Capabilities
    3. 39.3 Process and File Capabilities
      1. 39.3.1 Process Capabilities
      2. 39.3.2 File Capabilities
      3. 39.3.3 Purpose of the Process Permitted and Effective Capability Sets
      4. 39.3.4 Purpose of the File Permitted and Effective Capability Sets
      5. 39.3.5 Purpose of the Process and File Inheritable Sets
      6. 39.3.6 Assigning and Viewing File Capabilities from the Shell
    4. 39.4 The Modern Capabilities Implementation
    5. 39.5 Transformation of Process Capabilities During exec()
      1. 39.5.1 Capability Bounding Set
      2. 39.5.2 Preserving root Semantics
    6. 39.6 Effect on Process Capabilities of Changing User IDs
    7. 39.7 Changing Process Capabilities Programmatically
    8. 39.8 Creating Capabilities-Only Environments
    9. 39.9 Discovering the Capabilities Required by a Program
    10. 39.10 Older Kernels and Systems Without File Capabilities
    11. 39.11 Summary
    12. 39.12 Exercise
  46. Chapter 40: Login Accounting
    1. 40.1 Overview of the utmp and wtmp Files
    2. 40.2 The utmpx API
    3. 40.3 The utmpx Structure
    4. 40.4 Retrieving Information from the utmp and wtmp Files
    5. 40.5 Retrieving the Login Name: getlogin()
    6. 40.6 Updating the utmp and wtmp Files for a Login Session
    7. 40.7 The lastlog File
    8. 40.8 Summary
    9. 40.9 Exercises
  47. Chapter 41: Fundamentals of Shared Libraries
    1. 41.1 Object Libraries
    2. 41.2 Static Libraries
    3. 41.3 Overview of Shared Libraries
    4. 41.4 Creating and Using Shared Libraries—A First Pass
      1. 41.4.1 Creating a Shared Library
      2. 41.4.2 Position-Independent Code
      3. 41.4.3 Using a Shared Library
      4. 41.4.4 The Shared Library Soname
    5. 41.5 Useful Tools for Working with Shared Libraries
    6. 41.6 Shared Library Versions and Naming Conventions
    7. 41.7 Installing Shared Libraries
    8. 41.8 Compatible Versus Incompatible Libraries
    9. 41.9 Upgrading Shared Libraries
    10. 41.10 Specifying Library Search Directories in an Object File
    11. 41.11 Finding Shared Libraries at Run Time
    12. 41.12 Run-Time Symbol Resolution
    13. 41.13 Using a Static Library Instead of a Shared Library
    14. 41.14 Summary
    15. 41.15 Exercise
  48. Chapter 42: Advanced Features of Shared Libraries
    1. 42.1 Dynamically Loaded Libraries
      1. 42.1.1 Opening a Shared Library: dlopen()
      2. 42.1.2 Diagnosing Errors: dlerror()
      3. 42.1.3 Obtaining the Address of a Symbol: dlsym()
      4. 42.1.4 Closing a Shared Library: dlclose()
      5. 42.1.5 Obtaining Information About Loaded Symbols: dladdr()
      6. 42.1.6 Accessing Symbols in the Main Program
    2. 42.2 Controlling Symbol Visibility
    3. 42.3 Linker Version Scripts
      1. 42.3.1 Controlling Symbol Visibility with Version Scripts
      2. 42.3.2 Symbol Versioning
    4. 42.4 Initialization and Finalization Functions
    5. 42.5 Preloading Shared Libraries
    6. 42.6 Monitoring the Dynamic Linker: LD_DEBUG
    7. 42.7 Summary
    8. 42.8 Exercises
  49. Chapter 43: Interprocess Communication Overview
    1. 43.1 A Taxonomy of IPC Facilities
    2. 43.2 Communication Facilities
    3. 43.3 Synchronization Facilities
    4. 43.4 Comparing IPC Facilities
    5. 43.5 Summary
    6. 43.6 Exercises
  50. Chapter 44: Pipes and FIFOs
    1. 44.1 Overview
    2. 44.2 Creating and Using Pipes
    3. 44.3 Pipes as a Method of Process Synchronization
    4. 44.4 Using Pipes to Connect Filters
    5. 44.5 Talking to a Shell Command via a Pipe: popen()
    6. 44.6 Pipes and stdio Buffering
    7. 44.7 FIFOs
    8. 44.8 A Client-Server Application Using FIFOs
    9. 44.9 Nonblocking I/O
    10. 44.10 Semantics of read() and write() on Pipes and FIFOs
    11. 44.11 Summary
    12. 44.12 Exercises
  51. Chapter 45: Introduction to System V IPC
    1. 45.1 API Overview
    2. 45.2 IPC Keys
    3. 45.3 Associated Data Structure and Object Permissions
    4. 45.4 IPC Identifiers and Client-Server Applications
    5. 45.5 Algorithm Employed by System V IPC get Calls
    6. 45.6 The ipcs and ipcrm Commands
    7. 45.7 Obtaining a List of All IPC Objects
    8. 45.8 IPC Limits
    9. 45.9 Summary
    10. 45.10 Exercises
  52. Chapter 46: System V Message Queues
    1. 46.1 Creating or Opening a Message Queue
    2. 46.2 Exchanging Messages
      1. 46.2.1 Sending Messages
      2. 46.2.2 Receiving Messages
    3. 46.3 Message Queue Control Operations
    4. 46.4 Message Queue Associated Data Structure
    5. 46.5 Message Queue Limits
    6. 46.6 Displaying All Message Queues on the System
    7. 46.7 Client-Server Programming with Message Queues
    8. 46.8 A File-Server Application Using Message Queues
    9. 46.9 Disadvantages of System V Message Queues
    10. 46.10 Summary
    11. 46.11 Exercises
  53. Chapter 47: System V Semaphores
    1. 47.1 Overview
    2. 47.2 Creating or Opening a Semaphore Set
    3. 47.3 Semaphore Control Operations
    4. 47.4 Semaphore Associated Data Structure
    5. 47.5 Semaphore Initialization
    6. 47.6 Semaphore Operations
    7. 47.7 Handling of Multiple Blocked Semaphore Operations
    8. 47.8 Semaphore Undo Values
    9. 47.9 Implementing a Binary Semaphores Protocol
    10. 47.10 Semaphore Limits
    11. 47.11 Disadvantages of System V Semaphores
    12. 47.12 Summary
    13. 47.13 Exercises
  54. Chapter 48: System V Shared Memory
    1. 48.1 Overview
    2. 48.2 Creating or Opening a Shared Memory Segment
    3. 48.3 Using Shared Memory
    4. 48.4 Example: Transferring Data via Shared Memory
    5. 48.5 Location of Shared Memory in Virtual Memory
    6. 48.6 Storing Pointers in Shared Memory
    7. 48.7 Shared Memory Control Operations
    8. 48.8 Shared Memory Associated Data Structure
    9. 48.9 Shared Memory Limits
    10. 48.10 Summary
    11. 48.11 Exercises
  55. Chapter 49: Memory Mappings
    1. 49.1 Overview
    2. 49.2 Creating a Mapping: mmap()
    3. 49.3 Unmapping a Mapped Region: munmap()
    4. 49.4 File Mappings
      1. 49.4.1 Private File Mappings
      2. 49.4.2 Shared File Mappings
      3. 49.4.3 Boundary Cases
      4. 49.4.4 Memory Protection and File Access Mode Interactions
    5. 49.5 Synchronizing a Mapped Region: msync()
    6. 49.6 Additional mmap() Flags
    7. 49.7 Anonymous Mappings
    8. 49.8 Remapping a Mapped Region: mremap()
    9. 49.9 MAP_NORESERVE and Swap Space Overcommitting
    10. 49.10 The MAP_FIXED Flag
    11. 49.11 Nonlinear Mappings: remap_file_pages()
    12. 49.12 Summary
    13. 49.13 Exercises
  56. Chapter 50: Virtual Memory Operations
    1. 50.1 Changing Memory Protection: mprotect()
    2. 50.2 Memory Locking: mlock() and mlockall()
    3. 50.3 Determining Memory Residence: mincore()
    4. 50.4 Advising Future Memory Usage Patterns: madvise()
    5. 50.5 Summary
    6. 50.6 Exercises
  57. Chapter 51: Introduction to POSIX IPC
    1. 51.1 API Overview
    2. 51.2 Comparison of System V IPC and POSIX IPC
    3. 51.3 Summary
  58. Chapter 52: POSIX Message Queues
    1. 52.1 Overview
    2. 52.2 Opening, Closing, and Unlinking a Message Queue
    3. 52.3 Relationship Between Descriptors and Message Queues
    4. 52.4 Message Queue Attributes
    5. 52.5 Exchanging Messages
      1. 52.5.1 Sending Messages
      2. 52.5.2 Receiving Messages
      3. 52.5.3 Sending and Receiving Messages with a Timeout
    6. 52.6 Message Notification
      1. 52.6.1 Receiving Notification via a Signal
      2. 52.6.2 Receiving Notification via a Thread
    7. 52.7 Linux-Specific Features
    8. 52.8 Message Queue Limits
    9. 52.9 Comparison of POSIX and System V Message Queues
    10. 52.10 Summary
    11. 52.11 Exercises
  59. Chapter 53: POSIX Semaphores
    1. 53.1 Overview
    2. 53.2 Named Semaphores
      1. 53.2.1 Opening a Named Semaphore
      2. 53.2.2 Closing a Semaphore
      3. 53.2.3 Removing a Named Semaphore
    3. 53.3 Semaphore Operations
      1. 53.3.1 Waiting on a Semaphore
      2. 53.3.2 Posting a Semaphore
      3. 53.3.3 Retrieving the Current Value of a Semaphore
    4. 53.4 Unnamed Semaphores
      1. 53.4.1 Initializing an Unnamed Semaphore
      2. 53.4.2 Destroying an Unnamed Semaphore
    5. 53.5 Comparisons with Other Synchronization Techniques
    6. 53.6 Semaphore Limits
    7. 53.7 Summary
    8. 53.8 Exercises
  60. Chapter 54: POSIX Shared Memory
    1. 54.1 Overview
    2. 54.2 Creating Shared Memory Objects
    3. 54.3 Using Shared Memory Objects
    4. 54.4 Removing Shared Memory Objects
    5. 54.5 Comparisons Between Shared Memory APIs
    6. 54.6 Summary
    7. 54.7 Exercise
  61. Chapter 55: File Locking
    1. 55.1 Overview
    2. 55.2 File Locking with flock()
      1. 55.2.1 Semantics of Lock Inheritance and Release
      2. 55.2.2 Limitations of flock()
    3. 55.3 Record Locking with fcntl()
      1. 55.3.1 Deadlock
      2. 55.3.2 Example: An Interactive Locking Program
      3. 55.3.3 Example: A Library of Locking Functions
      4. 55.3.4 Lock Limits and Performance
      5. 55.3.5 Semantics of Lock Inheritance and Release
      6. 55.3.6 Lock Starvation and Priority of Queued Lock Requests
    4. 55.4 Mandatory Locking
    5. 55.5 The /proc/locks File
    6. 55.6 Running Just One Instance of a Program
    7. 55.7 Older Locking Techniques
    8. 55.8 Summary
    9. 55.9 Exercises
  62. Chapter 56: Sockets: Introduction
    1. 56.1 Overview
    2. 56.2 Creating a Socket: socket()
    3. 56.3 Binding a Socket to an Address: bind()
    4. 56.4 Generic Socket Address Structures: struct sockaddr
    5. 56.5 Stream Sockets
      1. 56.5.1 Listening for Incoming Connections: listen()
      2. 56.5.2 Accepting a Connection: accept()
      3. 56.5.3 Connecting to a Peer Socket: connect()
      4. 56.5.4 I/O on Stream Sockets
      5. 56.5.5 Connection Termination: close()
    6. 56.6 Datagram Sockets
      1. 56.6.1 Exchanging Datagrams: recvfrom() and sendto()
      2. 56.6.2 Using connect() with Datagram Sockets
    7. 56.7 Summary
  63. Chapter 57: Sockets: UNIX Domain
    1. 57.1 UNIX Domain Socket Addresses: struct sockaddr_un
    2. 57.2 Stream Sockets in the UNIX Domain
    3. 57.3 Datagram Sockets in the UNIX Domain
    4. 57.4 UNIX Domain Socket Permissions
    5. 57.5 Creating a Connected Socket Pair: socketpair()
    6. 57.6 The Linux Abstract Socket Namespace
    7. 57.7 Summary
    8. 57.8 Exercises
  64. Chapter 58: Sockets: Fundamentals of TCP/IP Networks
    1. 58.1 Internets
    2. 58.2 Networking Protocols and Layers
    3. 58.3 The Data-Link Layer
    4. 58.4 The Network Layer: IP
    5. 58.5 IP Addresses
    6. 58.6 The Transport Layer
      1. 58.6.1 Port Numbers
      2. 58.6.2 User Datagram Protocol (UDP)
      3. 58.6.3 Transmission Control Protocol (TCP)
    7. 58.7 Requests for Comments (RFCs)
    8. 58.8 Summary
  65. Chapter 59: Sockets: Internet Domains
    1. 59.1 Internet Domain Sockets
    2. 59.2 Network Byte Order
    3. 59.3 Data Representation
    4. 59.4 Internet Socket Addresses
    5. 59.5 Overview of Host and Service Conversion Functions
    6. 59.6 The inet_pton() and inet_ntop() Functions
    7. 59.7 Client-Server Example (Datagram Sockets)
    8. 59.8 Domain Name System (DNS)
    9. 59.9 The /etc/services File
    10. 59.10 Protocol-Independent Host and Service Conversion
      1. 59.10.1 The getaddrinfo() Function
      2. 59.10.2 Freeing addrinfo Lists: freeaddrinfo()
      3. 59.10.3 Diagnosing Errors: gai_strerror()
      4. 59.10.4 The getnameinfo() Function
    11. 59.11 Client-Server Example (Stream Sockets)
    12. 59.12 An Internet Domain Sockets Library
    13. 59.13 Obsolete APIs for Host and Service Conversions
      1. 59.13.1 The inet_aton() and inet_ntoa() Functions
      2. 59.13.2 The gethostbyname() and gethostbyaddr() Functions
      3. 59.13.3 The getservbyname() and getservbyport() Functions
    14. 59.14 UNIX Versus Internet Domain Sockets
    15. 59.15 Further Information
    16. 59.16 Summary
    17. 59.17 Exercises
  66. Chapter 60: Sockets: Server Design
    1. 60.1 Iterative and Concurrent Servers
    2. 60.2 An Iterative UDP echo Server
    3. 60.3 A Concurrent TCP echo Server
    4. 60.4 Other Concurrent Server Designs
    5. 60.5 The inetd (Internet Superserver) Daemon
    6. 60.6 Summary
    7. 60.7 Exercises
  67. Chapter 61: Sockets: Advanced Topics
    1. 61.1 Partial Reads and Writes on Stream Sockets
    2. 61.2 The shutdown() System Call
    3. 61.3 Socket-Specific I/O System Calls: recv() and send()
    4. 61.4 The sendfile() System Call
    5. 61.5 Retrieving Socket Addresses
    6. 61.6 A Closer Look at TCP
      1. 61.6.1 Format of a TCP Segment
      2. 61.6.2 TCP Sequence Numbers and Acknowledgements
      3. 61.6.3 TCP State Machine and State Transition Diagram
      4. 61.6.4 TCP Connection Establishment
      5. 61.6.5 TCP Connection Termination
      6. 61.6.6 Calling shutdown() on a TCP Socket
      7. 61.6.7 The TIME_WAIT State
    7. 61.7 Monitoring Sockets: netstat
    8. 61.8 Using tcpdump to Monitor TCP Traffic
    9. 61.9 Socket Options
    10. 61.10 The SO_REUSEADDR Socket Option
    11. 61.11 Inheritance of Flags and Options Across accept()
    12. 61.12 TCP Versus UDP
    13. 61.13 Advanced Features
      1. 61.13.1 Out-of-Band Data
      2. 61.13.2 The sendmsg() and recvmsg() System Calls
      3. 61.13.3 Passing File Descriptors
      4. 61.13.4 Receiving Sender Credentials
      5. 61.13.5 Sequenced-Packet Sockets
      6. 61.13.6 SCTP and DCCP Transport-Layer Protocols
    14. 61.14 Summary
    15. 61.15 Exercises
  68. Chapter 62: Terminals
    1. 62.1 Overview
    2. 62.2 Retrieving and Modifying Terminal Attributes
    3. 62.3 The stty Command
    4. 62.4 Terminal Special Characters
    5. 62.5 Terminal Flags
    6. 62.6 Terminal I/O Modes
      1. 62.6.1 Canonical Mode
      2. 62.6.2 Noncanonical Mode
      3. 62.6.3 Cooked, Cbreak, and Raw Modes
    7. 62.7 Terminal Line Speed (Bit Rate)
    8. 62.8 Terminal Line Control
    9. 62.9 Terminal Window Size
    10. 62.10 Terminal Identification
    11. 62.11 Summary
    12. 62.12 Exercises
  69. Chapter 63: Alternative I/O Models
    1. 63.1 Overview
      1. 63.1.1 Level-Triggered and Edge-Triggered Notification
      2. 63.1.2 Employing Nonblocking I/O with Alternative I/O Models
    2. 63.2 I/O Multiplexing
      1. 63.2.1 The select() System Call
      2. 63.2.2 The poll() System Call
      3. 63.2.3 When Is a File Descriptor Ready?
      4. 63.2.4 Comparison of select() and poll()
      5. 63.2.5 Problems with select() and poll()
    3. 63.3 Signal-Driven I/O
      1. 63.3.1 When Is “I/O Possible” Signaled?
      2. 63.3.2 Refining the Use of Signal-Driven I/O
    4. 63.4 The epoll API
      1. 63.4.1 Creating an epoll Instance: epoll_create()
      2. 63.4.2 Modifying the epoll Interest List: epoll_ctl()
      3. 63.4.3 Waiting for Events: epoll_wait()
      4. 63.4.4 A Closer Look at epoll Semantics
      5. 63.4.5 Performance of epoll Versus I/O Multiplexing
      6. 63.4.6 Edge-Triggered Notification
    5. 63.5 Waiting on Signals and File Descriptors
      1. 63.5.1 The pselect() System Call
      2. 63.5.2 The Self-Pipe Trick
    6. 63.6 Summary
    7. 63.7 Exercises
  70. Chapter 64: Pseudoterminals
    1. 64.1 Overview
    2. 64.2 UNIX 98 Pseudoterminals
      1. 64.2.1 Opening an Unused Master: posix_openpt()
      2. 64.2.2 Changing Slave Ownership and Permissions: grantpt()
      3. 64.2.3 Unlocking the Slave: unlockpt()
      4. 64.2.4 Obtaining the Name of the Slave: ptsname()
    3. 64.3 Opening a Master: ptyMasterOpen()
    4. 64.4 Connecting Processes with a Pseudoterminal: ptyFork()
    5. 64.5 Pseudoterminal I/O
    6. 64.6 Implementing script(1)
    7. 64.7 Terminal Attributes and Window Size
    8. 64.8 BSD Pseudoterminals
    9. 64.9 Summary
    10. 64.10 Exercises
  71. Appendix A: Tracing System Calls
  72. Appendix B: Parsing Command-Line Options
  73. Appendix C: Casting the NULL Pointer
  74. Appendix D: Kernel Configuration
  75. Appendix E: Further Sources of Information
  76. Appendix F: Solutions to Selected Exercises
  77. Bibliography
  78. Index

Product information

  • Title: The Linux Programming Interface
  • Author(s): Michael Kerrisk
  • Release date: October 2010
  • Publisher(s): No Starch Press
  • ISBN: 9781593272203