1.1 OS là gì?
Operating System (OS) là phần mềm đứng giữa phần cứng và ứng dụng. Nó là "lớp trung gian" cung cấp:
- Trừu tượng hoá phần cứng: app không cần biết RAM hãng nào, ổ cứng giao thức gì — chỉ cần gọi
read/write - Quản lý tài nguyên: chia CPU, RAM, disk, network cho nhiều process công bằng
- Bảo vệ & cô lập: process này không thể "đọc trộm" RAM của process khác hoặc làm crash hệ thống
- Cung cấp API thống nhất: open/close/read/write — cùng API cho file, socket, device
Không có OS, mỗi app sẽ phải tự viết code điều khiển từng loại phần cứng — chuyện không tưởng. OS giải quyết bài toán đó một lần.
1.2 4 chức năng chính của OS
- Process Management: tạo, hủy, lập lịch, đồng bộ, giao tiếp giữa các process. Đây là chương 2-7 của giáo trình.
- Memory Management: cấp phát RAM cho process, tạo virtual memory, paging, swap. Chương 8-9.
- File System & Storage: tổ chức dữ liệu trên disk, file/directory, permission. Chương 10.
- I/O & Device Driver: giao tiếp với keyboard, mouse, disk, network, GPU thông qua driver. Liên quan chương 10.
OS hiện đại còn có: networking stack, security/permission, virtualization (KVM, container), GUI...
1.3 User Space vs Kernel Space
Đây là khái niệm cốt lõi của OS. CPU hỗ trợ ít nhất 2 mức privilege (chế độ thực thi):
Kernel Space (Ring 0 trên x86)
- Có quyền tối cao: truy cập mọi RAM, mọi I/O port, mọi instruction
- Chỉ kernel chạy ở đây
- Lỗi ở đây = kernel panic (crash toàn hệ)
User Space (Ring 3 trên x86)
- Quyền hạn chế: chỉ truy cập memory của process mình, không gọi được instruction nguy hiểm
- App của bạn (Chrome, VS Code, Node.js) chạy ở đây
- Lỗi ở đây = segmentation fault (chỉ crash 1 process, OS vẫn sống)
CPU mode bit (1 flag trong CPU register) xác định đang chạy mode nào. Khi syscall, CPU tự động chuyển từ user mode sang kernel mode (mode switch). Khi kernel xử lý xong, chuyển ngược lại.
- Mode Switch: chuyển từ user mode sang kernel mode (hoặc ngược lại) — vẫn cùng một process. Rất nhanh.
- Context Switch: chuyển CPU từ process A sang process B — phải lưu/restore trạng thái CPU. Tốn hơn.
1.4 System Call — cầu nối user và kernel
User app không thể tự đọc/ghi disk, gửi packet network, tạo process — vì những việc đó đòi hỏi quyền kernel. Vậy app làm cách nào?
Câu trả lời: System Call (syscall). App "yêu cầu" kernel làm việc thay mình bằng cách gọi syscall. Đây là cánh cửa duy nhất giữa user space và kernel.
// Trong C, mọi I/O đều qua syscall
#include <unistd.h>
int main() {
write(1, "Hello\n", 6); // syscall write(fd, buf, count)
return 0;
}
Khi gọi write:
- App đặt syscall number (vd
1cho write trên Linux x86_64) vào CPU register - App đặt arguments vào các register khác
- App thực thi instruction
syscall(hoặcint 0x80trên 32-bit) - CPU tự động: lưu user state, chuyển sang kernel mode, nhảy đến syscall handler
- Kernel tra bảng syscall, gọi hàm tương ứng (vd
sys_write) - Kernel thực hiện công việc (ghi vào terminal, vào file...)
- Kernel restore user state, chuyển về user mode
- App tiếp tục chạy
Trong JavaScript / Node.js?
// Mọi I/O trong Node đều cuối cùng cũng là syscall
const fs = require('fs');
fs.writeFileSync('/tmp/hello.txt', 'Hi!');
// Node → libuv → C call write() → kernel sys_write() → device driver → disk
Khi bạn dùng console.log, fs.readFile, http.get — tất cả cuối cùng đều là syscall.
1.5 Syscall Lifecycle — chi tiết
Tốn bao nhiêu thời gian? 1 syscall trên CPU hiện đại tốn ~100-300 nanoseconds.
Nghe nhanh, nhưng nếu app gọi syscall trong vòng lặp triệu lần, có thể trở thành bottleneck.
Đây là lý do fwrite (buffered) nhanh hơn write (unbuffered) — nó gom nhiều thao tác thành 1 syscall.
1.6 Common Syscalls — phải biết
| Syscall | Chức năng | Chương liên quan |
|---|---|---|
fork | Tạo process con (copy parent) | Ch.02 |
execve | Thay thế process hiện tại bằng program khác | Ch.02 |
wait | Parent đợi child kết thúc | Ch.02 |
exit | Process tự kết thúc | Ch.02 |
clone | Tạo thread (Linux-specific) | Ch.03 |
open / close | Mở / đóng file, trả về file descriptor | Ch.10 |
read / write | Đọc / ghi qua fd | Ch.10 |
mmap / munmap | Map file/memory vào address space | Ch.08 |
brk / sbrk | Mở rộng heap | Ch.08 |
pipe | Tạo pipe IPC | Ch.05 |
kill | Gửi signal đến process | Ch.05 |
socket / connect / accept | Network | Ch.05, 10 |
select / poll / epoll | I/O multiplexing | Ch.10 |
ioctl | Thao tác đặc biệt với device | — |
Linux x86_64 có ~330 syscalls. Bạn không cần thuộc hết — hiểu top 20 là đủ.
1.7 Trace syscall thực tế với strace
strace là công cụ Linux ghi lại mọi syscall mà 1 process gọi. Cực hữu ích để debug và học OS.
# Trace lệnh ls
strace ls /tmp 2>&1 | head -30
# Output (đã rút gọn):
execve("/usr/bin/ls", ["ls", "/tmp"], 0x...) = 0
brk(NULL) = 0x...
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY) = 3
read(3, "...", 832) = 832
close(3) = 0
openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY) = 3
mmap(NULL, 145296, PROT_READ, ...) = 0x...
...
openat(AT_FDCWD, "/tmp", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
getdents64(3, /* 5 entries */, 32768) = 144
write(1, "file1.txt file2.txt\n", 21) = 21
close(3) = 0
exit_group(0) = ?
Bạn thấy gì? Một lệnh ls đơn giản gọi mấy chục syscall: load shared library, mở thư mục, read entries, in ra stdout, đóng.
Filter syscall theo tên
# Chỉ trace syscall liên quan đến file
strace -e openat,read,write,close ls /tmp
# Trace + đếm số lần mỗi syscall
strace -c ls /tmp
# % time seconds usecs/call calls errors syscall
# ------ ----------- ----------- --------- --------- ----------------
# 25.00 0.000125 12 10 openat
# 20.00 0.000100 11 9 mmap
# ...
Trên macOS: dtrace / dtruss
# macOS không có strace, dùng dtruss (cần sudo + SIP off một phần)
sudo dtruss ls /tmp 2>&1 | head -20
strace -c ls. Quan sát các syscall bạn vừa học (openat,
read, write, close, mmap...). Đây là khoảnh khắc bạn "chạm" vào kernel lần đầu.
1.8 Monolithic vs Microkernel
Monolithic Kernel
Toàn bộ OS (scheduler, memory, FS, driver, network stack) chạy trong một không gian kernel duy nhất.
- Ưu: nhanh — gọi function trong cùng kernel = direct call
- Nhược: bug ở bất kỳ component nào = kernel panic toàn hệ
- Ví dụ: Linux, BSD, Windows NT (hybrid nhưng nghiêng monolithic)
Microkernel
Kernel chỉ giữ tối thiểu: scheduler, IPC, memory cơ bản. Các service khác (FS, driver, network) chạy ở user space.
- Ưu: độ tin cậy cao — driver crash không sập kernel; dễ test/verify (vd seL4 đã được formal verify)
- Nhược: chậm hơn — gọi service phải qua IPC
- Ví dụ: Minix, QNX, seL4, MINIX-based Intel ME
Hybrid Kernel
Cố trộn ưu điểm cả hai. macOS XNU, Windows NT.
1.9 Boot Process — máy khởi động thế nào?
Từ lúc bạn bấm nút Power đến khi shell hiện ra:
- BIOS/UEFI chạy từ ROM trên mainboard. Kiểm tra hardware (POST), tìm boot device.
- Bootloader (vd GRUB) load từ MBR/EFI partition. Hiển thị menu chọn OS, load kernel image vào RAM.
- Kernel bắt đầu chạy: khởi tạo memory, detect hardware, load drivers, mount root filesystem.
- init/systemd (PID 1) chạy. Đây là process đầu tiên ở user space, làm parent cho mọi process khác. Khởi động services (cron, network, sshd...).
- Login screen hoặc shell hiện ra. Bạn đăng nhập, getty/login spawn shell.
# Xem PID 1 trên Linux
ps -p 1 -o comm=
# Output: systemd (hoặc init trên hệ cổ)
# Toàn bộ process tree
ps auxf | head -20
Bài tập
Mở Linux/macOS terminal. Chạy strace -c ls (Linux) hoặc sudo dtruss ls (macOS).
Liệt kê 5 syscall xuất hiện nhiều nhất.
Viết một chương trình C in "Hello" mà KHÔNG dùng printf. Chỉ dùng write(1, ...).
Viết loop gọi getpid() 10 triệu lần. Đo thời gian. So sánh với 10 triệu phép toán i++.
Sự khác biệt đo overhead syscall.
Tự nghiên cứu: trên Linux/macOS, làm thế nào để "tạo" segfault chủ ý? (Hint: dereference null pointer trong C). Quan sát output. Có ảnh hưởng đến process khác không? Đến OS không?
Trên máy bạn, PID 1 là gì? ps -p 1 -o comm= trên Linux. Trên Docker container thường là gì? Tại sao?
🧪 Quiz cuối chương
Câu 1. Syscall là gì?
Đáp án: cách user app yêu cầu kernel. Syscall là cánh cửa duy nhất giữa user space và kernel space. CPU thực hiện mode switch khi syscall xảy ra.
Câu 2. Mode Switch khác Context Switch ở đâu?
Đáp án: Mode switch không đổi process, Context switch đổi. Context switch tốn hơn vì phải lưu/restore PCB.
Câu 3. Linux dùng kernel architecture gì?
Đáp án: Monolithic. Toàn bộ Linux kernel chạy cùng không gian, nhưng có hỗ trợ load module động (kmod).
Câu 4. Tại sao app không thể truy cập trực tiếp phần cứng?
Đáp án: vì cô lập & bảo vệ. CPU mode bit ngăn user app chạy instruction nguy hiểm. Kernel kiểm soát quyền truy cập.
Câu 5. Trong Linux, PID 1 thường là?
Đáp án: init/systemd. PID 1 là parent của mọi process khác. Trên container, có thể là process bạn chạy (vd node app.js).
Câu 6. Khi C code gọi printf("Hi"), syscall thực sự xảy ra là?
Đáp án: write. printf là wrapper của libc, cuối cùng gọi syscall write(1, ...).
Câu 7. Lệnh strace dùng để?
Đáp án: trace syscall. Cực hữu ích để debug và học OS.
Câu 8. Microkernel "an toàn hơn" monolithic vì?
Đáp án: cô lập services. Driver crash trong monolithic = kernel panic. Trong microkernel = chỉ restart service.
Tổng kết chương 1
- ✅ OS = lớp trung gian giữa app và hardware; 4 chức năng: process, memory, file, I/O
- ✅ User space (app, ring 3) vs Kernel space (kernel, ring 0)
- ✅ System call = cánh cửa duy nhất giữa hai thế giới
- ✅ Mode switch ≠ Context switch
- ✅ Common syscalls:
fork,execve,open,read,write,mmap,pipe,socket - ✅ strace để quan sát syscall thật
- ✅ Monolithic (Linux) vs Microkernel (seL4) — đánh đổi tốc độ vs an toàn
- ✅ Boot: BIOS → bootloader → kernel → init/systemd → shell