# Building & Debugging a Linux Kernel Module: Process Logger and Memory Monitor

## 📌 Project: Process Logger & Memory Monitor Kernel Module

**Project Name:** `proc_mem_logger`

This project demonstrates how to write, debug, and safely operate a **loadable Linux kernel module** that periodically inspects system state from kernel space.

The module logs:
- All currently running processes
- Free RAM and swap memory
- Periodic output every 5 seconds using kernel timers

All output is written to the kernel log buffer and can be inspected using `dmesg` or `journalctl`.

This project is ideal for developers learning **Linux kernel internals, kernel timers, process structures, and memory APIs**.

---

## 🎯 Objective

Write a loadable kernel module that:

- Logs all running processes every 5 seconds  
- Monitors free RAM and swap usage periodically  
- Outputs results to the kernel log (`dmesg`)  
- Optionally triggers alerts when memory usage exceeds a threshold  

No external hardware is required.  
Safe to test on:
- Virtual machines  
- Ubuntu laptops or desktops  

---

## 🧩 Core Kernel Concepts Used

### 1. Kernel Timers
- Uses `struct timer_list`
- Schedules periodic execution using `mod_timer()`
- Proper cleanup during module unload to prevent crashes

### 2. Process Traversal
- Iterates through all processes using `for_each_process`
- Logs PID and process name (`task->comm`)
- Demonstrates safe access to kernel task structures

### 3. Memory Information
- Uses `si_meminfo()` to read system RAM and swap
- Correct conversion from **pages → bytes → MB**

### 4. Kernel Logging
- Uses `printk(KERN_INFO ...)`
- Debugged issues related to kernel loglevel filtering

### 5. Module Lifecycle Management
- Clean `init` and `exit` handlers
- Timer safely stopped during `rmmod`

---

## ▶️ Building and Running the Module

Load the module:
```bash
sudo insmod proc_mem_logger.ko
```

Check kernel output:
```bash
sudo dmesg | tail -50
```

Unload the module:
```bash
sudo rmmod proc_mem_logger
```

Watch logs in real time:
```bash
sudo dmesg -W
# or
sudo journalctl -k -f
```

---

## 🐞 Kernel Module Debugging: proc_mem_logger

### 1️⃣ Problem

The module was intended to log:
- Free RAM and swap memory
- Active processes (PID + name)

**Symptoms observed:**
- No output visible in `dmesg`
- Memory values reported as `0 MB`
- Module loaded successfully but appeared inactive

---

### 2️⃣ Initial Troubleshooting

#### Step 1: Check kernel log access

```bash
ls -l /dev/kmsg
```

`/dev/kmsg` is the kernel log buffer interface.  
Root must have read/write access to see kernel messages.

---

#### Step 2: Test kernel logging manually

```bash
echo "TEST_KMSG" | sudo tee /dev/kmsg
```

Verify:
```bash
dmesg | tail -n 20
sudo journalctl -k | tail -n 20
```

Result:  
`TEST_KMSG` appeared, confirming kernel logging was working correctly.

---

#### Step 3: Adjust kernel loglevel

```bash
echo 7 | sudo tee /proc/sys/kernel/printk
```

**Explanation:**
- Kernel loglevels range from 0–7
- `KERN_INFO` messages (level 6) may be hidden
- Setting loglevel to 7 enables all messages

---

### 3️⃣ Reloading the Module

```bash
sudo rmmod proc_mem_logger 2>/dev/null
sudo insmod proc_mem_logger.ko
sudo dmesg -W
```

After this, kernel messages began appearing as expected.

---

## ❗ Issue: Memory Values Showing 0 MB

### Root Cause

`si_meminfo()` returns values in **pages**, not bytes.

**Incorrect code:**
```c
i.freeram >> 20;
```

This shifts the page count directly, resulting in `0`.

---

### ✅ Correct Fix

```c
(i.freeram * PAGE_SIZE) >> 20;
(i.freeswap * PAGE_SIZE) >> 20;
```

### Why This Works
- `freeram * PAGE_SIZE` → bytes
- `>> 20` → megabytes

---

## 📋 Key Commands and Their Purpose

| Command | Purpose |
|------|------|
| `ls -l /dev/kmsg` | Verify kernel log buffer |
| `echo "TEST_KMSG" \| sudo tee /dev/kmsg` | Test kernel logging |
| `dmesg -W` | Watch kernel logs live |
| `journalctl -k -f` | Follow kernel logs via systemd |
| `echo 7 > /proc/sys/kernel/printk` | Enable INFO-level logs |
| `sudo insmod` | Load kernel module |
| `sudo rmmod` | Remove kernel module |

---

## ✅ Final Outcome

After applying all fixes:

- Processes are logged correctly every 5 seconds
- Free RAM and swap values are displayed accurately in MB
- Timer callback executes reliably without crashes
- Kernel logs are visible in real time

---

## 🧠 Key Takeaways / Learning Outcomes

- Kernel timers enable periodic execution in kernel space
- `for_each_process` safely iterates through all tasks
- `si_meminfo()` reports memory in pages, not bytes
- Kernel loglevels directly affect printk visibility
- Clean module unload is essential for kernel stability

---

## 🚀 Next Steps / Improvements

- Log CPU usage using `task->utime` and `task->stime`
- Expose data via `/proc/proc_mem_logger` instead of printk
- Filter only high CPU / high memory processes
- Make timer interval configurable via module parameters
- Add timestamps and rate limiting to logs

---

## 🏁 Closing Notes

This project is an excellent foundation for:
- Linux kernel development
- Embedded Linux work
- Systems programming interviews
- Understanding real kernel data structures

The module is safe to run on:
- Virtual machines
- Development laptops

It can be scaled further with `/proc` interfaces, CPU tracking, and alerting mechanisms.

