Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

CPU Context Switching and Linux Scheduler Queues

Tech 1

Registers and Process Context

Consider a basic C function:

int calculate_total(int a, int b)
{
    int result = 0;
    result = a + b;
    return result;
}
int main()
{
    int value = calculate_total(5, 7);
    return 0;
}

Local variables on the stack disappear after the function returns. The fact that callers can still receive a return value relies on CPU registers. The eax register, for example, stores intermediate values and return data. Another critical register is eip (the instruction pointer, also called the program counter), which tells the OS where execution currently resides.

All transient data that a process leaves inside CPU registers is called its hardware context. Although there is only one physical set of registers, each process maintains its own logical context. During a switch:

  1. When process A first runs, registers hold its context.
  2. If process B needs to execute, A's current register values (including eip) are saved into A's Process Control Block (PCB).
  3. B's context is then loaded into the registers, overwriting the previous contents.
  4. Later, when A resumes, its saved context is restored from the PCB back into the registers, and execution continues from the saved eip.

Scheduling Queues in Linux 2.6

Process switching is driven by the kernel’s scheduling queues.

Priority Ranges

  • Real‑time priorities: 0 – 99
  • Conventional priorities: 100 – 139 (corresponds to the nice value range)

Active and Expired Queues

The scheduler contains two sets of structures: nr_active, bitmap[5], and queue[140].

  • Active queue holds processes that still have time sllices remaining, ordered by priority.
  • queue[140] is an array of runqueues; the array index equals the priority level. Threads of the same priority are managed with FIFO ordering.
  • nr_active counts how many processes are in the runnable state.

A naive traversal of all 140 queues to find the highest‑priority runnable process would be inefficient. The bitmap[5] (5 × 32 bits = 160 bits) acts as a lookup mask. Each bit corresponds to a queue, indicating whether it is non‑empty, enabling the scheduler to locate the first non‑empty queue in O(1) time.

Expired queue mirrors the active queue’s structure but holds processes whose time slices are exhausted. When the active queue is empty, time slices are recalculated for processes in the expired queue.

Active and Expired Pointers

Two pointers control scheduling:

  • active always points to the current active queue.
  • expired always points to the expired queue.

Once the active queue is drained, the two pointers are swapped. The previous expired queue becomes the new active queue, giving all those processes a fresh execution window.

Why Two Queues?

Suppose the active queue contains processes with priorities 80 and 60. The kernel will run priority‑60 processes first. If new priority‑60 processes keep arriving, they might starve priority‑80 processes. To prevent this imbalance, newly arriving processes are placed into the expired queue. The active queue shrinks while the expired queue grows. Swapping the pointers after the active queue empties ensures fair scheduling across priorities.

Program Arguments from the Command Line

The main function can accept parameters:

int main(int parameter_count, char *argument_vector[])
  • parameter_count (commonly argc) stores the number of arguments.
  • argument_vector (common argv) is an array of strings.

Printing them reveals their origin:

#include <stdio.h>
int main(int argc, char *argv[])
{
    for (int i = 0; i < argc; i++)
    {
        printf("[%d] %s\n", i, argv[i]);
    }
    return 0;
}

The shell concatenates the command‑line string, splits it by spaces, and passes the resulting pieces to main. This mechanism lets a single binary exhibit different behaviors based on input flags.

Building a Miniature Calculator

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    if (argc != 4)
    {
        printf("Usage: %s <operation> <op1> <op2>\n", argv[0]);
        printf("Operations: -add -sub -mul -div\n");
        return 1;
    }

    int left  = atoi(argv[2]);
    int right = atoi(argv[3]);

    if (strcmp(argv[1], "-add") == 0)
        printf("%d + %d = %d\n", left, right, left + right);
    else if (strcmp(argv[1], "-sub") == 0)
        printf("%d - %d = %d\n", left, right, left - right);
    else if (strcmp(argv[1], "-mul") == 0)
        printf("%d * %d = %d\n", left, right, left * right);
    else if (strcmp(argv[1], "-div") == 0)
    {
        if (right == 0)
            printf("Error: division by zero\n");
        else
            printf("%d / %d = %d\n", left, right, left / right);
    }
    else
        printf("Unknown operation. Use -add, -sub, -mul, or -div.\n");

    return 0;
}

Emulating the touch Command

Understanding command‑line arguments allows re‑implementation of standard tools:

#include <stdio.h>

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("touch: missing file operand\n");
        return 1;
    }

    FILE *f = fopen(argv[1], "w");
    if (f)
        fclose(f);

    return 0;
}

The reason ls -l and ls -a -l produce different outputs is that the shell passes different argv arrays to main. Varying the arguments changes the control flow inside the program, enabling a single executable to support multiple options.

Related Articles

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.