file descriptor:

0 → standard input (stdin)
1 → standard output (stdout)
2 → standard error (stderr)

dup() and dup2()

  • dup(fd) → creates a new file descriptor number pointing to the same
    file as fd.
  • dup2(fd, newfd) → same, but you choose the new descriptor number
    (closes it first if open).

File Descriptor

It’s just a number the OS gives you when you open a file.

Think of it as a ticket number to access the file.

int fd = open("data.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
// fd might be 3 because 0,1,2 are stdin, stdout, stderr
write(fd, "Hello\n", 6); // writes to the file via fd

dup(fd)

Makes a copy of the descriptor → new number, same file.

int newfd = dup(fd);  // creates newfd (e.g., 4) same file as fd
write(newfd, "World\n", 6); // continues writing at same position

dup2(fd, newfd)

Copies fd into exactly newfd.

If newfd was open, it closes it first.

dup2(fd, STDOUT_FILENO); // now printf goes into fd's file
printf("This goes into the file!\n");

unistd.h

It declares many system call interfaces for Unix-like operating systems (Linux, macOS, BSD, etc.).

Useful functions:

#include <string.h> strlen()

open(...)

flags → control the behavior of opening the file (read/write mode, create, truncate, append, etc.).

mode_t → sets the permissions of the file only when it’s created.

How to read a file

#include "source.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// read a file line by line and then identify a specific text in ""
// remember to free() after using sscanf's buffer
void find_movie_score() {
    char* buffer = NULL;
    size_t capacity = 0;
    FILE* fp = fopen("movies.csv", "r");
    int year;
    int score;
    char movie[30];
    getline(&buffer, &capacity, fp);
    while (getline(&buffer, &capacity, fp) != -1) {
        // Read up to 29 characters, stopping if a " is seen.
        // in this case 29 means 1 character less than the 30 length long buffer,  which is safer
        int result = sscanf(buffer, "%d,%d,\"%29[^\"]\"", &year, &score, movie);
        // == is not safe
        if (strcmp(movie, "New_York,_New_York") == 0) {
            printf("%d", score);
            
            break;
        }
    }
    free(buffer);
    fclose(fp);
    
    return;
}

Process memory layout

  • OS Kernel Space
  • Stack
  • ...
  • Heap
  • BSS
  • Data
  • Text
  • ...

OS Kernel Space

Reserved for the operating system kernel and device drivers.

User processes cannot access this space directly (for protection and stability).

Contains critical code and data structures needed to manage the system.

Stack

~Grows downwards in memory (toward lower addresses).~

Stores function call information: return addresses, local variables, and function parameters.

Managed automatically by the compiler and runtime.

Each thread in a process gets its own stack.

Heap

Grows upwards in memory (toward higher addresses).

Used for dynamically allocated memory (e.g., via malloc in C, new in C++).

Managed by the programmer (or garbage collector in managed languages).

Can fragment over time due to frequent allocations and deallocations.

BSS (Block Started by Symbol)

Contains uninitialized global and static variables.

Typically zero-initialized at program startup.

For example: static int count; (without an initializer).

Data Segment

Contains initialized global and static variables.

Divided into:

Read/write section: for variables that can change during execution.

Read-only section: for constants that must not change.

Example: static int count = 5;

Text Segment (Code Segment)

Stores the compiled program instructions (machine code).

Usually marked as read-only to prevent accidental modification of code.

May be shared among processes running the same program to save memory.

VIM

Press Esc (goes back to Normal mode).
Then type one of these commands (they start with :):

:w → Save (write) the file.
:q → Quit.
:wq → Save and quit.
:q! → Quit without saving.

Arrow keys → work as expected.
Or use the classic Vim keys:

h → move left
l → move right
j → move down
k → move up

Moving by words

w → jump forward to the beginning of the next word
e → jump to the end of the current/next word
b → jump backward to the beginning of a word

Moving by lines

0 (zero) → move to the start of the line
^ → move to the first non-space character of the line
$ → move to the end of the line

Moving by text blocks

gg → go to the top of the file
G → go to the bottom of the file
:n → jump to line n (example: :15 goes to line 15)

Searching

/word → search forward for “word”
?word → search backward for “word”
n → repeat the last search in the same direction
N → repeat the last search in the opposite direction

Scrolling

Ctrl + d → scroll half a page down
Ctrl + u → scroll half a page up
Ctrl + f → scroll one full page down
Ctrl + b → scroll one full page up

Split Verticle or Horizontal:

vim -O main.c utils.h
vim -o main.c utils.h
:vsplit utils.h // inside vim
vim -p main.c utils.h // taps alternative

Moving Between Splits

Ctrl-w h → move to left split

Ctrl-w l → move to right split

Ctrl-w j → move to split below

Ctrl-w k → move to split above

Ctrl-w w → cycle through all windows

Resizing Splits

Ctrl-w = → equalize all splits

Ctrl-w > → increase width

Ctrl-w < → decrease width

Ctrl-w + → increase height

Ctrl-w - → decrease height

GDB

break main // set break point to function main()
delete // clean all breakpoints
layout src // open interface
info breakpoint // check breakpoint information

Cursor Movement

Keys    Action
Ctrl-a    Move to beginning of line
Ctrl-e    Move to end of line
Ctrl-b    Move backward one character (like ←)
Ctrl-f    Move forward one character (like →)
Alt-b    Move backward one word
Alt-f    Move forward one word

Editing Text

Keys    Action
Ctrl-d    Delete character under cursor
Backspace    Delete character before cursor
Ctrl-k    Kill (cut) text from cursor to end of line
Ctrl-u    Kill (cut) text from cursor to beginning of line
Alt-d    Kill (cut) word after cursor
Alt-Backspace    Kill (cut) word before cursor

History Navigation

Keys    Action
Ctrl-p    Previous command (like ↑)
Ctrl-n    Next command (like ↓)
Ctrl-r    Reverse search in history
Ctrl-g    Cancel search

Misc

Keys    Action
Ctrl-l    Clear the screen (like clear)
Ctrl-y    Yank (paste) last killed text
Ctrl-t    Swap character before cursor with current one

Get started with your assignment

// open session for: fa25-cs341-276.cs.illinois.edu
cd fa25_cs341_NETID
git remote add release https://github.com/illinois-cs-coursework/fa25_cs341_.release.git
git pull release main --allow-unrelated-histories --no-rebase
git push origin main

git add submission.txt
git commit -m "My Submission" (commit your work to git).
git push origin main (push your committed work to Github – Required for your changes to be visible to the Autograder).

WSL

If you want to visit some files in your WSL via Windows file explorer, use

\\wsl$\Ubuntu\home\

Valgrind

valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./shell
valgrind --leak-check=full --show-leak-kinds=all ./your_program