Inspecting Process Memory Usage
Using top
PID – Process ID
USER – Owner
PR – Priority (lower = higher)
NI – Nice value
VIRT – Virtual memory
RES – Physical memory
SHR – Shared memory
S – State (S=sleep, R=run, Z=zombie, N=negative nice)
%CPU – CPU usage
%MEM – Physical memory ratio
TIME+ – Cumulative CPU time
COMMAND – Executable name
Using ps
Common flags:
a– All terminals-A/-e– Every processu– User-oriented formatx– Include detached processes
Typical pattern:
ps aux | grep <keyword>
Kernel Module Basics
Dynamic Loading vs Static Linking
- Static: Driver compiled into kernel; large image, slow debug cycle.
- Dynamic:
.komodules loaded at runtime viainsmod/rmmod; smaller kernel, faster iteration.
Boot Flow on Embedded Boards
Bootloader (U-Boot) → Kernel → Mount rootfs → Init → Applications
Minimal rootfs directories:
/etc configs
/bin essential user binaries
/sbin essential system binaries
/lib shared libraries & modules
/dev device nodes
Writing a Simple Character Driver
Skeleton for an LED driver:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#define DEV_NAME "led_demo"
#define GPIO_BASE 0x56000050
#define GPIO_SIZE 16
static int major;
static void __iomem *gpio_con, *gpio_dat;
static ssize_t led_write(struct file *f, const char __user *buf,
size_t len, loff_t *off)
{
char kbuf;
if (copy_from_user(&kbuf, buf, 1))
return -EFAULT;
if (kbuf == '1')
iowrite32(ioread32(gpio_dat) & ~((1<<4)|(1<<5)|(1<<6)), gpio_dat);
else
iowrite32(ioread32(gpio_dat) | ((1<<4)|(1<<5)|(1<<6)), gpio_dat);
return len;
}
static int led_open(struct inode *i, struct file *f)
{
u32 val = ioread32(gpio_con);
val &= ~((0x3<<(4*2)) | (0x3<<(5*2)) | (0x3<<(6*2)));
val |= ((0x1<<(4*2)) | (0x1<<(5*2)) | (0x1<<(6*2)));
iowrite32(val, gpio_con);
return 0;
}
static const struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
};
static int __init led_init(void)
{
major = register_chrdev(0, DEV_NAME, &led_fops);
gpio_con = ioremap(GPIO_BASE, GPIO_SIZE);
gpio_dat = gpio_con + 1;
return 0;
}
static void __exit led_exit(void)
{
unregister_chrdev(major, DEV_NAME);
iounmap(gpio_con);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
Process, Thread, Coroutine
| Aspect | Process | Thread | Coroutine |
|---|---|---|---|
| Resource owner | Seperate VM | Shares VM | Shares thread |
| Switch cost | High (kernel) | Medium (kernel) | Low (user) |
| Typical use | CPU-bound jobs | I/O-bound jobs | Massive concurrency |
Copy-on-write after fork() defers page duplication until write occurs.
Inter-Process Communication
| Mechanism | Traits |
|---|---|
| Anonymous pipe | Half-duplex, parenet–child only, 4 kB buffer, byte stream |
| Named pipe (FIFO) | Path-based, any processes, same semantics as pipe |
| Message queue | Structured records, kernel linked-list, size limits |
| Shared memory | Fastest, needs external sync (e.g., semaphores) |
| Unix domain socket | Local full-duplex, socket API |
| Signal | Async notification, limited payload |
Virtual Memory Essentials
- Physical RAM: Actual DRAM.
- Virtual address space: Per-process contiguous range, mapped via page tables.
- Swap: Disk area for evicted pages.
- Shared memory: Same physical frames mapped into multiple processes.
Address translation (simplified):
- Split VA into page number + offset.
- Walk page table (page number → frame number).
- Combine frame number + offset → physical address.
- On miss, raise page fault → load from disk.
I/O Multiplexing
Stages of a read():
- Wait for data ready.
- Copy data from kernel to user buffer.
Comparison
| Call | Max FDs | Complexity | Data Structure | Edge Trigger |
|---|---|---|---|---|
| select | 1024 | O(n) | fd_set | No |
| poll | none | O(n) | pollfd array | No |
| epoll | none | O(1) | RB tree + list | Yes (ET/LT) |
epoll workflow:
epoll_create()→ obtain epfd.epoll_ctl(epfd, ADD, fd, &event)→ insert into RB tree.epoll_wait(epfd, events, maxevents, timeout)→ sleep until ready list non-empty.
File Descriptors and VFS
- FD: Small integer index into per-process open-file table.
- VFS layer provides uniform
open/read/write/ioctlfor any filesystem or device.
Byte Order Detection
int is_little_endian(void) {
uint16_t x = 0x1;
return *(uint8_t *)&x;
}
Static vs Global Variables
static int g;– visible only in current translation unit.int g;– external linkage, visible to other units viaextern.