AMSA

Week 2: Linux syscalls, tasks and ProcFS

Ferran Aran Domingo
Oriol Agost Batalla
Pablo Fraile Alonso

Goals for today

  • Any questions from the previous session?
  • Learn how the CPU reacts to external input.
  • Understand how we interact with the kernel.
  • What are tasks and how we can visualize them with ProcFS.
  • Present and explain Prac-2.1

Recap

Interrupts

How the CPU works

Devices interactions with the CPU

  • But wait, how can we interact with external devices? We don’t have the instructions on our code!

  • The devices connected to your computer, use a mechanism called “interrupts” for being aware of the events.

    Warning

    This is a super-summarized path (and incorrect one), there’s no PIC controller, the IRQ numbers probably are wrong. But it’s only for academic purposes.

We didn’t configure the IDT table…

  • Well, yes, one of the first steps of the kernel is to tell the cpu to point the IDT table to his part of the code that has the logic for the IDT table.

  • So, now, when we receive an interrupt is the kernel code the one that will be executed! Nice!

Tip

You can see the IDT table inside the linux kernel source code, and where it is setup.

Did we get it?

  • It is very important to understand (at a concept level) interrupts, so we can understand further things in this session (and course)
  • Did we get it?
  • Sure?
  • Really really sure?

User-Space and Kernel-Space

CPU Protection

  • The CPU allows multiple levels of “security”, called rings.
  • Each ring (starting from ring 0) restrict access to certain instructions.
  • Linux uses the ring 0 (do “whatever you want” ring) as the Kernel Space and ring 4 (the ring where you’re most limited) as UserSpace (where your programs run).

Warning

Due to restricted access to memory and I/O ports in Ring 4, userspace can do almost nothing to the outside world without calling on the kernel. It can’t open files, send network packets, print to the screen, or allocate memory.

But, I can do a lot of stuff with my userspace programs… How is that possible?

Syscalls

  • Well, we can write to files, so…. we’re executing some code in ring 0.
  • We execute code in ring 0 asking the kernel if can do the job for us, and then return the result.
  • This request is a concept named “syscall” (system call).

Tip

You can see all the linux kernel syscalls on this list

Example

This python code:

file = open("test.txt", mode='r')
lines = file.readlines()
print(lines)

Does the following:

Tip

You can see the system calls the program is doing under the hood, with the strace tool

What are syscalls (really)

  • We need to switch to ring 0 and there’s no instruction for this. We have to "notify" the kernel.
  • We saw that we can notify things to the kernel using interrupts (remember the IDT table).
  • Syscalls are a certain type of interrupt (if you see the linux kernel IDT table, the number 128 one 1).
  • So yes, the 128 entry in the IDT redirects to a function that analyzes the system call, and execute the kernel function related to it.

Syscall example

For example, if we want to execute the open system call, we could, in userspace:

mov edx,4       ; message length
mov ecx,msg     ; message to write
mov ebx,1       ; file descriptor (stdout)
mov eax,4       ; system call number (sys_write)
int 0x80        ; interrupt! Number 128 (0x80 in hex)

Tip

Since the Linux Kernel 2.6, it supports the syscall instruction instead of doing an interrupt 128 (0x80) for syscalls. You can read more here

Brief summary

  • The CPU executes instructions linearly, one after another.

  • To interact with the outside world, it relies on interrupts.

  • The CPU has different privilege levels, called rings, which help the operating system enforce security and control. Our programs usually run in the least privileged ring (user mode), which means we can’t execute certain instructions directly.

  • If we want to perform I/O operations or access system resources, we need to ask the kernel to do it for us.

  • We communicate with the kernel through system calls (syscalls), which are essentially a type of interrupt.

  • The kernel also sets up interrupts on its own to manage processes (like pausing one, switching to another, or handling various system events.) You can read more here.

Kthreads, Processes and Threads

Are you already familiar with those?

Definitions

  • The kernel has an abstraction of a running program, and calls it “task (task_struct)”.

  • Depending of the type of task, we can differentiate between:

    • Processes: Tasks that abstract a running program.
      • Example: execute in a shell cat /etc/passwd.
    • Threads: Tasks that have independent sequences of execution within the same process. They share the process’s address space and resources but maintain separate control flows, allowing concurrent operations.
      • Example: $cat file.txt file2.txt file3.txt could create one thread per file.
    • Kthreads: Threads that run within the kernel and share cpu time with other processes/threads.
      • Example: The kernel has one thread for executing the scheduling algorithm.
  • Threads and processes, can be created with the clone syscall.

Processes

  • The one you did at operating systems with the “fork” syscall 1.
  • A process is an operating system abstraction that groups together multiple resources:
  • An address space
  • One or more threads
  • Opened files
  • Sockets
  • Semaphores
  • Shared memory regions
  • Timers
  • Signal handlers
  • Many other resources and status information
  • Example: Execute the cat program.

Threads

  • You’ll study them on SCP, where you’ll create them with the glibc-pthread library (which uses the clone syscall underneath).

  • A thread is the basic unit that the kernel process scheduler uses to allow applications to run the CPU. Has the following characteristics:

    • Each thread has its own stack and together with the register values it determines the thread execution state.
    • A thread runs in the context of a process and all threads in the same process share the resources.
    • The kernel schedules threads (tasks) not processes.
  • They’re identified via tgid.

  • Example: If I have multiple files on the cat program maybe I need only different execution paths, and I can create one thread for each one.

Kthreads

  • Sometimes the kernel core or device drivers need to perform blocking operations and thus they need to run in process context.

  • Kernel threads are used exactly for this and are a special class of tasks that don’t “userspace” resources.

  • A tgid will also be used to identify them.

  • Example: ksoftirqd/X. Where X is the number of cores. Is the scheduler kthread for the core X on your computer.

ProcFS

Definition

  • Finally, the thing we’re doing on this assignment!
  • The kernel exposes a /proc folder on the filesystem, that shows you information about the tasks running on the system.
  • htop is a program that uses procfs, and shows you the list of tasks and properties.

Properties of procfs: Processes

  • Doing an ls -la /proc shows a the list of pids/tgids of processes and kthreads (NOT Threads!).
  • If a process (without threads) is launched (e.g., $cat ...), running $ls /proc/${pidOfCat}/task will list a single thread. This thread’s tgid (thread group ID) will be the same as pidOfCat, since the process consists of only one thread of execution (one task_struct inside the kernel).
  • You can see more info about the current process or thread, inside cat /proc/${pid}/stat or cat /proc/${pid}/status

Properties of procfs: Kernel Threads

  • Doing an ls -la /proc hhows a the list of pids/tgids of processes and kthreads (NOT Threads!).
  • You can see more info about the current process or thread, inside cat /proc/${tgid}/stat 1 or cat /proc/${tgid}/status
  • A kernel thread, doesn’t have an executable, so cat /proc/${tgid}/exe should give no such file or directory.

Properties of procfs: Threads

  • But each process can have multiple threads spawned, this are listed on: /proc/{pid_of_process}/tasks/{tgid}

    Warning

    Be aware that, if we have a process that spawns two threads, it will have 3 entries inside the tasks folder:

    • One that is equal to the process id (tgid == pid)
    • Two that are the spawned threads.
  • Once you have a tgid, you can do ls -la /proc/${tgid} or cd into it.

Example

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <sys/types.h>

void* read_file(void* filename) {
    char* file = (char*)filename;
    pid_t pid = getpid(); // Process ID
    pid_t tid = gettid(); // Thread ID (TID/TGID)
    pid_t ppid = getppid(); // Parent PID
    printf("Reading %s | PID=%d, TGID=%d, PPID=%d\n", file, pid, tid, ppid);
    sleep(1); // Fake read_file implementation...
    pthread_exit(NULL);
}

int main() {
    pid_t pid = getpid();
    pid_t tid = gettid();  // Main thread ID
    printf("cat process started | PID=%d, TGID=%d, PPID=%d\n", pid, tid, getppid());

    pthread_t t1, t2, t3;

    pthread_create(&t1, NULL, read_file, "one.txt");
    pthread_create(&t2, NULL, read_file, "two.txt");
    pthread_create(&t3, NULL, read_file, "three.txt");

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    printf("cat process exiting | PID=%d\n", pid);
    return 0;
}

And in Htop, you should see the following:

  └── bash # (process)                     PID=4912, TGID=4912, PPID=1
      └── cat # (process, child from bash) PID=4914, TGID=4914, PPID=4912
           └── read one.txt # (thread)     PID=4914, TGID=4915, PPID=4912
           └── read two.txt # (thread)     PID=4914, TGID=4916, PPID=4912
           └── read three.txt # (thread)   PID=4914, TGID=4917, PPID=4912

Quizz

Syscalls questions

  • Why we need syscalls?

  • Can we create kthreads with the clone syscall?

ProcFS Questions

  • Can I have a thread without a process?

  • Where’s The /proc filesystem saved?

References

Additional Exercices

If you really want to understand a little bit more what happens under the hood, you can do the following exercices. Be aware that you should read the “Really Recommended References” first, and then try to do this exercices.

Activity 2.1

Ready to have some fun? Check out the second AMSA activity here!