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