Renaming all folders

This commit is contained in:
Fabio Scotto di Santolo
2025-08-22 16:21:42 +02:00
parent 331308b2d8
commit 538cb4559e
45 changed files with 9 additions and 9 deletions

View File

@@ -0,0 +1,212 @@
# Chapter 9 - Memory Management
This document summarizes the key concepts from **Chapter 9: Memory Management** in *Linux System Programming, 2nd Edition* by Robert Love*. It provides an overview of how memory is managed in user space, the role of the kernel, common functions for allocation and manipulation, and techniques to optimize and debug memory usage.
---
## Overview
Memory management in Linux is a fundamental component of system programming. It involves allocating, using, and releasing memory safely and efficiently. Proper memory handling avoids fragmentation, memory leaks, and undefined behavior.
The chapter focuses on:
- How user-space processes interact with the kernel for memory allocation.
- The process memory layout and its components.
- Allocation strategies in both heap and stack.
- Advanced techniques like memory mapping and page locking.
- Debugging tools for memory issues.
---
## Key Topics
### 1. Memory Layout of a Process
Every Linux process has a well-defined memory layout, divided into segments:
- **Text Segment** Holds the compiled machine code of the program. Typically marked read-only and executable to prevent accidental modification.
- **Data Segment** Contains initialized global and static variables.
- **BSS Segment** Holds uninitialized global and static variables, which the kernel initializes to zero at program start.
- **Heap** Dynamic memory allocated at runtime using `malloc`, `calloc`, or `realloc`. Grows upward as needed.
- **Stack** Stores function call frames, local variables, and return addresses. Grows downward on most architectures.
- **Memory Mappings** Regions created with `mmap()`, commonly used for shared libraries and large allocations.
> Understanding this layout is essential for writing efficient, low-level programs and debugging memory-related issues.
---
### 2. Dynamic Memory Allocation
Dynamic allocation functions allow flexible use of memory at runtime:
- **malloc(size_t size)** Allocates a memory block of the given size without initialization.
- **calloc(size_t nmemb, size_t size)** Allocates memory for an array of `nmemb` elements, initializing all bytes to zero.
- **realloc(void \*ptr, size_t size)** Resizes an existing memory block, preserving its contents up to the smaller of the old and new sizes.
- **free(void \*ptr)** Releases previously allocated memory.
#### Common pitfalls
- **Memory leaks** Occur when allocated memory is not freed before losing all references to it.
- **Double free** Freeing the same memory block twice, which causes undefined behavior.
- **Use-after-free** Accessing a memory block after it has been freed, leading to crashes or data corruption.
---
### 3. `brk` and `sbrk`
Historically, `brk()` and `sbrk()` were used to manipulate the program break, which defines the end of the processs data segment.
- `brk()` sets the end of the data segment.
- `sbrk()` increments (or decrements) the break value.
Modern applications rarely use these functions directly; instead, `malloc` and related functions manage them internally. These interfaces are considered low-level and non-portable.
---
### 4. Memory Mapping with `mmap`
`mmap()` maps files or anonymous memory into the processs address space.
#### Advantages
- Eliminates the need for additional copies when reading files.
- Enables efficient handling of large files and inter-process communication.
#### Typical use cases
- Memory-mapped file I/O.
- Shared memory regions for IPC.
- Allocating large anonymous memory regions.
To release mappings, use **munmap()**. Unlike `malloc`, which uses the heap, `mmap` provides greater flexibility for aligning memory and mapping hardware devices.
---
### 5. Advanced Memory Techniques
Several specialized APIs provide advanced control over memory:
- **mprotect()** Changes access permissions (read, write, execute) for a memory region.
- **shm_open() / shm_unlink()** Creates and removes POSIX shared memory objects for inter-process communication.
- **posix_memalign()** Allocates memory aligned to a specific boundary, useful for SIMD operations or page-aligned buffers.
These functions are essential in performance-sensitive and real-time systems.
---
### 6. Debugging Memory Issues
The GNU C Library provides several functions to inspect and analyze memory usage at runtime:
- **mallinfo()**
Returns a `struct mallinfo` with statistics about memory allocation, such as total allocated space, number of free blocks, and fragmentation levels.
- **malloc_usable_size(void *ptr)**
Returns the actual usable size of an allocated block. This value may be larger than the size requested from `malloc()` due to alignment or internal overhead.
- **malloc_trim(size_t pad)**
Attempts to return unused memory from the heap back to the operating system, retaining `pad` bytes for future allocations. Useful for long-running processes to reduce memory footprint.
- **malloc_stats()**
Prints detailed statistics about memory allocation directly to `stderr`.
This includes information about the heap, allocated blocks, and free space.
#### Notes
- These functions are **GNU-specific** and may not be portable across different C libraries or UNIX-like systems.
- They are primarily intended for **debugging and profiling**, not for production code paths that require high performance.
- Use them to analyze fragmentation patterns, memory usage trends, and allocator behavior during development or testing.
---
### 7. Stack-Based Allocation
Stack allocation can be an efficient alternative for temporary buffers:
- **alloca(size_t size)** Allocates memory on the calling functions stack frame. The allocated memory is automatically released when the function returns, so `free()` is unnecessary.
#### Advantages
- Extremely fast allocation and deallocation.
- Ideal for short-lived buffers with known size limits.
#### Limitations
- Memory is valid only within the function scope. Returning a pointer to stack memory results in undefined behavior.
- Excessive allocation can lead to **stack overflow** and program crashes.
- `alloca()` is not part of the ISO C standard, but it is available as a POSIX or compiler-specific extension.
**Example**:
```c
void example(size_t size) {
char *buffer = alloca(size);
// Use buffer safely within this function only
}
```
---
### 8. Manipulating Memory
C provides several functions for low-level memory manipulation:
- **memset(void \*s, int c, size_t n)**
Fills a block of memory with a given byte value.
Example:
```c
memset(buffer, 0, sizeof(buffer)); // Zero out buffer
```
- **memcpy(void \*dest, const void \*src, size_t n)**
Copies `n` bytes from `src` to `dest`. Behavior is undefined if regions overlap.
- **memmove(void \*dest, const void \*src, size_t n)**
Like `memcpy`, but handles overlapping memory correctly.
- **memcmp(const void \*s1, const void \*s2, size_t n)**
Compares two memory regions byte by byte, returning:
- `< 0` if `s1` < `s2`
- `0` if equal
- `> 0` if `s1` > `s2`
- **memchr(const void \*s, int c, size_t n)**
Scans the n bytes of memory pointed at by s for the character c, which is interpreted as an unsigned char
- **memmem(const void \*haystack, size_t haystacklen, const void \*needle, size_t needlelen)**
Returns a pointer to the first occurrence of the subblock needle, of length needlelen bytes, within the block of memory haystack, of length haystacklen bytes.
If the function does not find needle in haystack, it returns NULL.
> This function is a GNU extension
These functions do not perform type checking or add null terminators, making them ideal for raw data operations but requiring caution to avoid buffer overruns.
---
### 9. Locking Memory
Linux provides mechanisms to lock memory pages into RAM:
- **mlock()** Locks a specific memory range, preventing it from being swapped out.
- **mlockall()** Locks all pages mapped by the calling process.
#### Use cases
- Real-time systems that must avoid page faults.
- Applications handling sensitive data such as encryption keys, ensuring they never hit disk.
After use, memory should be unlocked with **munlock()** or **munlockall()**.
---
## Key Takeaways
- Understanding the process memory layout is critical for writing efficient and safe programs.
- Dynamic allocation with `malloc` and its variants is powerful but requires careful management to avoid leaks and corruption.
- Use `mmap` for large or shared allocations and `alloca` for small, temporary buffers.
- Memory manipulation functions provide high performance but require strict attention to bounds and alignment.
---
## References
- *Linux System Programming, 2nd Edition* Robert Love, OReilly Media.
- `man malloc`, `man mmap`, `man alloca`, `man mprotect`, `man mlock`.