| Title and Copyright Information |
| About This Manual |
| Audience |
| New and Changed Features |
| Scope of the Manual |
| Organization |
| Related Documentation |
| Reader's Comments |
| Conventions |
| 1 | Introduction to Kernel Modules |
| 1.1 | What Is a Kernel Module? |
| 1.1.1 | Purpose of a Kernel Module |
| 1.1.2 | Kernel Module Environment |
| 1.1.3 | Designing a Kernel Module |
| 1.2 | Writing a Kernel Module Key Tasks |
| 1.2.1 | Required Tasks |
| 1.2.1.1 | Initializing a Kernel Module |
| 1.2.1.2 | Creating the Attribute Table |
| 1.2.1.3 | Using Callbacks |
| 1.2.1.4 | Working in Kernel Modules |
| 1.2.2 | Additional Tasks |
| 1.2.2.1 | Working in an SMP Environment |
| 1.2.2.2 | Working with Kernel Threads |
| 1.2.3 | Building a Kernel Module |
| 2 | Module Initialization |
| 2.1 | The configure Routine |
| 2.1.1 | Parameters |
| 2.1.2 | Request Codes |
| 2.1.3 | Return Status Values |
| 2.2 | Module Initialization |
| 2.2.1 | Receiving the CFG_OP_CONFIGURE Request |
| 2.2.1.1 | Implementing Statically or Dynamically Loaded Kernel Modules |
| 2.2.1.2 | Tracking the Configuration |
| 2.2.1.3 | Allocating Memory for Data Structures |
| 2.2.2 | Receiving the CFG_OP_UNCONFIGURE Request |
| 3 | Module Attributes |
| 3.1 | The Attribute Table |
| 3.2 | Attribute Table Entry |
| 3.2.1 | Attribute Data Types |
| 3.2.2 | Operations Allowed on an Attribute |
| 3.3 | Attribute Get Requests |
| 3.4 | Attribute Set Requests |
| 4 | Dispatch Point Callbacks |
| 4.1 | Understanding the UNIX Boot Timeline |
| 4.2 | Why Use Callbacks? |
| 4.3 | Dispatch Points on the Boot Timeline |
| 4.4 | Implementing Callbacks in Your Kernel Module |
| 4.4.1 | Coding Callbacks |
| 4.4.1.1 | Calling the register_callback Routine |
| 4.4.1.2 | Writing the Callback Routine |
| 4.4.2 | Registering Callbacks |
| 4.4.3 | Nesting Callbacks and Unregistering Callbacks |
| 4.4.4 | Defining New Dispatch Points in Your Kernel Module |
| 5 | Kernel-Mode Capabilities |
| 5.1 | Using String Routines |
| 5.1.1 | Comparing Two Null-Terminated Strings |
| 5.1.2 | Comparing Two Strings by Using a Specified Number of Characters |
| 5.1.3 | Copying a Null-Terminated Character String |
| 5.1.4 | Copying a Null-Terminated Character String with a Specified Limit |
| 5.1.5 | Returning the Number of Characters in a Null-Terminated String |
| 5.2 | Using Data Copying Routines |
| 5.2.1 | Copying a Series of Bytes with a Specified Limit |
| 5.2.2 | Zeroing a Block of Memory in Kernel Address Space |
| 5.2.3 | Zeroing a Block of Memory in User Address Space |
| 5.2.4 | Copying Data from User Address Space to Kernel Address Space |
| 5.2.5 | Copying Data from Kernel Address Space to User Address Space |
| 5.2.6 | Moving Data Between User Virtual Space and System Virtual Space |
| 5.3 | Using Kernel-Related Routines |
| 5.3.1 | Printing Text to the Console and Error Logger |
| 5.3.2 | Putting a Calling Process to Sleep |
| 5.3.3 | Waking Up a Sleeping Process |
| 5.3.4 | Initializing a Timer (Callout) Queue Element |
| 5.3.5 | Removing Scheduled Routines from the Timer (Callout) Queue |
| 5.3.6 | Setting the Interrupt Priority Mask |
| 5.3.7 | Allocating Memory |
| 5.3.7.1 | Allocating Data Structures with MALLOC |
| 5.3.7.2 | Freeing Up Dynamically Allocated Memory |
| 5.4 | Working with System Time |
| 5.4.1 | Understanding System Time Concepts |
| 5.4.1.1 | How a Kernel Module Uses Time |
| 5.4.1.2 | How System Time is Created |
| 5.4.2 | Fetching System Time |
| 5.4.3 | Modifying a Timestamp |
| 5.4.4 | Enabling Applications to Convert a Kernel Timestamp to a String |
| 5.4.5 | Delaying the Calling Routine a Specified Number of Microseconds |
| 5.5 | Using Kernel Threads |
| 5.6 | Using Locks |
| 6 | Symmetric Multiprocessing and Locking Methods |
| 6.1 | Understanding Hardware Issues Related to Synchronization |
| 6.1.1 | Atomicity |
| 6.1.2 | Alignment |
| 6.1.3 | Granularity |
| 6.2 | Locking in a Symmetric Multiprocessing Environment |
| 6.3 | Comparing Simple Locks and Complex Locks |
| 6.3.1 | Simple Locks |
| 6.3.2 | Complex Locks |
| 6.4 | Choosing a Locking Method |
| 6.4.1 | Who Has Access to a Particular Resource |
| 6.4.2 | Prevention of Access to a Resource While a Kernel Thread Sleeps |
| 6.4.3 | Length of Time the Lock Is Held |
| 6.4.4 | Execution Speed |
| 6.4.5 | Size of Code Blocks |
| 6.4.6 | Summary of Locking Methods |
| 6.5 | Choosing the Resources to Lock in the Module |
| 6.5.1 | Read-Only Resources |
| 6.5.2 | Device Control Status Register Addresses |
| 6.5.3 | Module-Specific Global Resources |
| 6.5.4 | System-Specific Global Resources |
| 6.5.5 | How to Determine the Resources to Lock |
| 6.5.5.1 | Step 1: Identify All Resources That You Might Lock |
| 6.5.5.2 | Step 2: Identify All of the Code Blocks in the Module That Manipulate the Resource |
| 6.5.5.3 | Step 3: Determine Which Locking Method Is Appropriate |
| 6.5.5.4 | Step 4: Determine the Granularity of the Lock |
| 7 | Simple Lock Routines |
| 7.1 | Declaring a Simple Lock Data Structure |
| 7.2 | Initializing a Simple Lock |
| 7.3 | Asserting Exclusive Access on a Resource |
| 7.4 | Releasing a Previously Asserted Simple Lock |
| 7.5 | Trying to Obtain a Simple Lock |
| 7.6 | Terminating a Simple Lock |
| 7.7 | Using the spl Routines with Simple Locks |
| 8 | Complex Lock Routines |
| 8.1 | Declaring a Complex Lock Data Structure |
| 8.2 | Initializing a Complex Lock |
| 8.3 | Performing Access Operations on a Complex Lock |
| 8.3.1 | Asserting a Complex Lock |
| 8.3.1.1 | Asserting a Complex Lock with Read-Only Access |
| 8.3.1.2 | Asserting a Complex Lock with Write Access |
| 8.3.2 | Releasing a Previously Asserted Complex Lock |
| 8.3.3 | Trying to Assert a Complex Lock |
| 8.3.3.1 | Trying to Assert a Complex Lock with Read-Only Access |
| 8.3.3.2 | Trying to Assert a Complex Lock with Write Access |
| 8.4 | Terminating a Complex Lock |
| 9 | Kernel Threads |
| 9.1 | Using Kernel Threads in Kernel Modules |
| 9.1.1 | Kernel Threads Execution |
| 9.1.2 | Issues Related to Using Kernel Threads |
| 9.1.3 | Kernel Threads Operations |
| 9.2 | Using the thread and task Data Structures |
| 9.3 | Creating and Starting a Kernel Thread |
| 9.3.1 | Creating and Starting a Kernel Thread with an Argument and Timeshare Scheduling Policy |
| 9.3.2 | Creating and Starting a Fixed-Priority Kernel Thread Dedicated to Interrupt Service |
| 9.4 | Blocking (Putting to Sleep) a Kernel Thread |
| 9.4.1 | Asserting That the Current Kernel Thread Is About to Block Until the Specified Event Occurs |
| 9.4.2 | Using the Symmetric Multiprocessor Sleep Routine |
| 9.5 | Unblocking (Awakening) Kernel Threads |
| 9.6 | Terminating a Kernel Thread |
| 9.7 | Setting a Timer for the Current Kernel Thread |
| 10 | Building a Kernel Module |
| 10.1 | Procedure for Building a Kernel Module |
| 10.1.1 | Step 1: Create a Directory to Contain the Source Files |
| 10.1.2 | Step 2: Copy the Source Files |
| 10.1.3 | Step 3: Create a files File Fragment |
| 10.1.4 | Step 4: Create a BINARY.list File |
| 10.1.5 | Step 5: Create the sysconfigtab File Fragment |
| 10.1.6 | Step 6: Create a Makefile |
| 10.1.7 | Step 7: Build the Kernel Module |
| 10.2 | Adding Your Module's Attributes |
| 10.3 | Statically Link a Kernel Module into a /vmunix Kernel |
| 10.3.1 | Step 1: Create a Kernel Build Directory |
| 10.3.2 | Step 2: Create a NAME.list File |
| 10.3.3 | Step 3: Run the doconfig Program |
| 10.3.4 | Step 4: Copy the New Kernel to the Root Directory |
| 10.3.5 | Step 5: Shut Down and Boot the System |
| 10.4 | Dynamically Load a Kernel Module |
| 10.4.1 | Step 1: Create the Appropriate Links |
| 10.4.2 | Step 2: Load the Kernel Module |
| 10.5 | Changing Attribute Values at Run Time |
| Glossary |
| Figures |
| 1-1 | Kernel Module Environment |
| 3-1 | Attribute Get Requests |
| 3-2 | Attribute Set Requests |
| 4-1 | Dispatch Points Along the Boot Timeline |
| 4-2 | Using the Kernel Callback Subsystem |
| 5-1 | Results of the strcmp Routine |
| 5-2 | Results of the strncmp Routine |
| 5-3 | Results of the strcpy Routine |
| 5-4 | Results of the strncpy Routine |
| 5-5 | Results of the strlen Routine |
| 5-6 | Results of the bcopy Routine |
| 5-7 | Results of the copyin Routine |
| 5-8 | Results of the copyout Routine |
| 5-9 | When Time Becomes Available During a System Boot |
| 6-1 | Why Locking Is Needed in an SMP Environment |
| 6-2 | Simple Locks Are Spin Locks |
| 6-3 | Complex Locks Are Blocking Locks |
| 7-1 | Two Instances of the xx Module Asserting an Exclusive Lock |
| 7-2 | One Instance of the xx Module Releasing an Exclusive Lock |
| 7-3 | The xx Module Trying to Assert an Exclusive Lock |
| 8-1 | Three Instances of the if_fta Module Asserting a Read-Only Complex Lock |
| 8-2 | Three Instances of the if_fta Module Asserting a Write Complex Lock |
| 8-3 | One Instance of the if_fta Module Releasing a Complex Write Lock |
| 8-4 | The if_fta Module Trying to Assert a Complex Read-Only Lock |
| 8-5 | The if_fta Module Trying to Assert a Complex Write Lock |
| 9-1 | Using Kernel Threads in a Kernel Module |
| Tables |
| 5-1 | Uses for spl Routines |
| 6-1 | Data Structure and Routines Associated with Simple Locks |
| 6-2 | Data Structure and Routines Associated with Complex Locks |
| 6-3 | SMP Characteristics for Locking |
| 6-4 | Kernel Module Resources for Locking |
| 6-5 | Locking Device Register Offset Definitions |
| 9-1 | Summary of Operations That Kernel Thread Routines Perform |
| Index |