C.A.Lee
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    5
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    --- robots: index, follow tags: NCTU, CS, 共筆, Unix description: 交大資工課程學習筆記 lang: zh-tw dir: ltr breaks: true disqus: calee GA: UA-100433652-1 --- 高等 UNIX 程式設計 -- 黃俊穎 === http://people.cs.nctu.edu.tw/~chuang/courses/unixprog unix107 up19peppa ## Syllbus - Unix 越來越熱門 - 老師: 黃俊穎 (chuang@cs.nctu.edu.tw) - Prerequiste - C / Cpp - (little) assembly (IA32, IA64) - OS - Computer network - W. Richard Stevens and Stephen A. Rago, "Advanced Programming in the UNIX Environment" - Topics - Fundamental tools - File & directories - file / standard IO - System data & info. - Process environment - Process control - Signals - Assembly - Threads - Thread control - Daemon - Advanced IO - Inter-process communication - Network IO - ... - 用 VM - 需要開 VT-x (BIOS) - Grading - Mid: 25% - Final: 35% - HW: 40% (3~6) ## Overview & env - prepar UNIX ```sh sudo apt-get install gcc g++ gdb make manpages-dev manpages-posix manpages-posix-dev ``` - Kernel ![](https://i.imgur.com/kxxeHvg.png) - Boot - OS loader (ex. grub) - 從特定位址 load program - Kernel init system hardware - first process - init - systemd - /bin/sh (系統救援時,可以叫 sh 先起來) - after process - mount - network - daemon - login interface - ... - File System (FS) - windows: partition base directory - linux: root base directory ![](https://i.imgur.com/exgCKEF.png) ![](https://i.imgur.com/yF3yRfW.png) - Filesystem Header Standard - Linux command - [LSB (Linux Stanard Base)](https://wiki.linuxfoundation.org/lsb/start) - [FHS (Filesystem Hierarchy Standard)](https://wiki.linuxfoundation.org/lsb/fhs) - 如何 touch 有 '-' 開頭的 file? (- 感覺會被 parse 成參數):用 `touch ./-aaa` - Redirection - `>` `<` - Pipe - `|` - man (manu page) - `man [section] command` - 不寫 section 了話都是 section 1 - `man -k command`: 找到有哪些 section - 標準 section - ![](https://i.imgur.com/LR7TBwt.png =300x) - Sample Code - http://people.cs.nctu.edu.tw/~chuang/courses/unixprog/resources/inclass-20160530.tar.gz (老師修改的 code) - https://people.cs.nctu.edu.tw/~chuang/courses/unixprog/resources/textbook-20180326.tar.gz (課本的 code) - Return value - 0: true, !0: false - `echo $?`: 上一個 process 的 return value - `||`: 如果前面 return true,就不用執行後面的 - `&&`: 如果前面 return true,才執行後面的 - Handle Program - argc, argv[] - getopt - getopt_long - Time - time command - real: average amount of time required per iteration, in microseconds. Time is measured in elapsed time, not CPU time. - user: user space 用的時間 - sys: kernel space - Error - return value - errno: error number(3) (global) - ![](https://i.imgur.com/L8lTK4G.png) - 轉換成看得懂的 - strerror - perror - Error Recovery ### Tools - Compiler - ex. gcc, clang, ... - gcc - `-S`: 生成 .s (assembly) - `-c`: 只編譯,不 link - `-l`: link library - `-I`: add include path - `-L`: add lib path - 大 project 建議分開 compile 再 link (Makefile) - 這樣單獨檔案被跟改時,不會需要所以 source code 都被重新 compiler 一次 - 不同語言 - 通常語言會各自加自己的 header 在變數名稱(text session)前面 - => 不同語言不能直覺直接 link - `nm`: 可以解析 object file 的指令(list symbols) ```cpp #ifdef__cplusplus (only needs for a C++ compiler) extern "C" { (declare that everything within the scope) int b(); (should be treated as C symbols, not C++ ) } #endif ``` - make, Makefile - Ref: https://www.gnu.org/software/make/manual/make.html - 簡化 build process - 管理相依性與多平台選擇參數問題 - 參數 - `-C`: 修改工作目錄 - `-f`: 指定檔案 (就不一定要叫做 Makefile 了) - `-j`: 同時編譯 - 內容 ```Makefile rulename: dependencies rule # comment split to\ multi-lines ``` - 預設變數 - `$@`: target 名稱 - `$<`: **第一個** prerequisite - `$?`: 比 target 新的 prerequisite - `$^`: 所有 prerequisite (會移除重複) - `$+`: `$^` 但不移除重複 ```Makefile haha: a b c a d echo $@ echo $< echo $? echo $^ echo $+ # output: # haha # a # a b c d # a b c d # a b c a d ``` - 注意,只要 rulename 內的任一檔案 timestemp 不同,make 都會把 rulename 內的全部 rule 再跑一次 - .PHONY: 不事先檢查檔案是否存在 - 在不指定開始的 rulename 時,會以第一個 rulename 開始執行 (不是 all) - `.c.o:`: .c 檔轉成 .o 檔 - 舊式,新式改成 `%.o: %.c` - `.c.o` [缺點](https://www.gnu.org/software/make/manual/make.html#Suffix-Rules) - GDB - `-g`: compile 時產生 debug synble,不用不影響 gdb 指令,但是會看不到 source code - debug symble 不會存 souce code,他是 link 到 source file,所以如果 source file compile 後又被改過,會看到錯誤的資訊 - command: - `list`: 列出 sourse code - `run`: always run from begin - `s/step`: 跳一行,但會跳進 function call (if esixt) - `n/next`: 跳一行 - `ni/nexti`: next instruction (asm level) - `p/print`: print source code - `c/continue`: 跳到下一個 break point - `b/break` - `layout {ams|regs|src}` - `bt/backtrace`: 查看 call stack - `x/FMT <address>`: 用 MFT 方式查看記憶體位址 - `fin/finish`: 從 call stack 中跳回上一層 - Core dump file - `ulimit` - ... - debug w/o asm - stript - ... ## File IO & Standard IO - File IO - file discriptor - 所有開啟的檔案在 kernel 下都有一個 FD 來描述(紀錄) - 非負整數 [0, OPEN_MAX-1] - STDIN_FILENO(0), STDOUT_FILENO(1), STDERR_FILENO(2) - Unbuffered IO - user space 下是沒有 buffer 的 - 直接跟直接跟 kernel 溝通 - 通常只有這五種: open, read, write, lseek, and close - 可以用 pipe 做重導向 - `a>b`: 將 FD a 重導向 FD b - `> file`: 通常不寫就是將 FD 1(stdout) 重導向 file - `|`: pipe() - Standard I/O - buffered IO - user space 下有 buffer - ex. fwrite() 事先寫入 buffer 才寫入 file - buffer 填滿後才一起塞入 write => 減少 kernel 呼叫 - 透過 wrapper of FD 存取 - stdin, stdout, and stderr - 透過 fileno() 可以看到 FD number - ex. - open(path, flag, mode) - mode: permission - rwxr-xr-x: 655 - flag: - O_RDONLY, O_WRONLY, O_RDWR - O_APPEND, O_CREAT, O_EXCL(exclusive?), O_TRUNC(把從在的檔案清空,讓看起來像 create 的), O_SYNC(去掉 device buffer 的影響) - create(path, mode) - close(fd) - process 結束時會自動 close 所有的 open file - lseek(fd, offset, whence) - 用來移動 file pointer (device 要可以 random access) - whence: SEEK_SET(最前), SEEK_CUR(目前), SEEK_END(最後) - 多用 lseek64(fd, offset64, whence) - Random access vs Sequential access - file: Random access - pipe: Sequential access - `/var/spool/cron/FIFO`: Sequential access - Large File Support (LFS) - 2GB 以上 - 需要 define _LARGEFILE64_SOURCE, _LARGEFILE_SOURCE 與 _FILE_OFFSET_BITS 64 (在 include 任何 c library header 前) - 開檔需要參數 O_LARGEFILE - `gcc –D_LARGEFILE64_SOURCE –D_LARGEFILE_SOURCE –D_FILE_OFFSET_BITS=64` - File hole: 一份檔案裡有部分空間沒有寫到,沒寫入的部分 FS 會自動填入 0 - 檔案大小是從第一個 pointer 到最後一個 pointer (最後接 EOF) - 檔案實際大小(硬碟消耗空間)是 4KB * n > 寫入大小 - ex. 寫 10byte + 跳 16374 + 寫 10byte - file size: 16394 B - write disk size: 8 KB - `ls -s`: 看 write byte - `strip`: re-format block write,有機會整理壓縮寫入 block size - ![](https://i.imgur.com/3OncVAa.png =400x) - ![](https://i.imgur.com/ZkVcn8R.png) ### File IO other issue - IO Efficiency - 如果 buffer size 太小,因為每次 read 都要 kernel call,效率會減低 - 如果 buffer size < block size - 每次 read 進 DMA 後,來到 disk 會是同一個 block => DMA 需要重複讀取一樣的資料 - File sharing - kernel 如何實作 file open - process table - table of file descriptors - v-node - ![](https://i.imgur.com/4SdKVv9.png =500x) - sharing 時 - 到 file pointer 時,都是 per process 的 - 然後將 file pointer 的 v-node 指向同一個 v-node - fork(),因為 file table 存在 heap (per process),所以會 duplicate 一份 - process-table 會複製一份,file table 也會複製一份,vnode 是同一份 - Atomic Operation - 如果開檔後,fork 一個新的 process,然後再把 file pointer 移到最後面,加入 10B - 會產生非預期操作 (unexpected order) - Atomic: 只用一個 x86 instruction 可以執行出一個 function call => 不用擔心 interrupt - pread, pwrite - pread: seek + read - pwrite: seek + write - open = check + create => interrupt - open(pathname, O_CREAT | O_EXCL, mode) - check + create 會在同時執行 (中間不會被中斷) - dup, dup2 (duplicate) - ![](https://i.imgur.com/IWINm1M.png =250x) - dup2 的 target fd 要確保關閉了 - dup(n): 將 fd{n} 的 file table entry 複製一份到最新關閉的 fd (target 由 fd 自己維護) - dup2(1, 3): 將 fd1 的 file table entry 複製一份到 fd3 (target 需要是 close 的) - ![](https://i.imgur.com/FcVeTVj.png =500x) - sync, fsync, fdatasync - 因為 IO 其實會先 queue 在 buffer 再一起寫入 - 跟 buffered IO 的 buffer(user space) 不同,是 kernel 裡的 buffer - 對某個 fd - fsync: filedata + metadata - fdatasync: filedata only - 所有檔案 - sync: filedata + metadata - 如果想要強迫寫入,可以用 sync - ioctl - 所有 device 在 UNIX 下都是 file => 可以用 ioctl access - dependency by driver - linux cross reference - /dev/fd - virtual file system - `/proc/[pid]/fd/` : 看 process 有維護的 fd ### Standard IO 最大的差別,stdio 有 **buffer**,他不會每次 call 都做 system call,而是只有在 buffer 被填滿時才 system call 寫入 - Buffering - 3 mode - fully buffered - 整份檔案 call 進 buffer - ex. fopen(..., "rb") 中的 `b` - ex. stdio - line buffered - 一行一行吃,在 buffer 中讀到 `\n` 時,再去跑一次 kernel call - ex. fopen(..., "rt") 中的 `t`,會讓這個 io 一行一行吃 - unbuffered - ex. stderr - fdopen(fd, mode) - 將指定 fd 的檔案的 fp 抓出來回傳,好處是之後可以直接用 file pointer 來操作這個 檔案 / io / device / ... - size_t fwrite(void *ptr, size_t obj_size, size_t nr_obj, FILE *fp); - 回傳寫入了幾個 object - 如果 size of obj 沒有寫完全,就是沒有寫入這個 obj - ex. `fwrite(pt, sizeof(double), 2, fp)` - 如果今天 pt 只有 2Byte,無法完全寫入一個 double 的長度,就會回傳 0 - fseek() - 暫存檔 - 一種直接被覆寫也不會怎麼樣的檔案 - `char *tmpnam(char *ptr)` - 會在 `/tmp/fileXXXXXX` 開出暫存檔 - 檔名相同時,會被 overwrite (危險) - `tmpfile(void)` - 推薦使用 ## File & Dir - linux 的 filename 除了 `/` 跟 `null` 外,都可以用 - 最多 255 character (PATH_MAX) - 每個 process 都有自己的 working directory - cwd (current working directory) - chdir (cd) - home dir 是使用者登入時的第一個 working dir - 在 `/etc/passwd` 設定 - file information: - api - `int stat(const char *path, struct stat *buf);` - `int fstat(int fd, struct stat *buf);` - `int lstat(const char *path, struct stat *buf);` - stat 與 lstat 幾乎一樣,lstat 不 follow symbolic link ### File information - file type - Regular file、Directory file、Block special file、Character special file、FIFO、Socket、Symbolic link - block special file 與 character special file 差在 random access - file permission (discentralized permission <-> SELinux) - Real UID, Real GID - 實際登入的人 - Effective UID, Effective GID - 確認檔案權限 - SUID, SGID - set UID - exec 會儲存狀態 - 當 SUID enabled 時,RUID 還是會是執行本人,但 EUID 就會變成程式檔案的擁有者 (SUID) - function: setuid(2), setgid(2) - 9bit permission - ![](https://i.imgur.com/PfdhZ2Y.png =300x) - access permission - dir 要有 x 權限 - 刪除檔案要有 dir wx 權限 - 可以用 id 指令來查看 id / `/etc/passwd` / `/etc/groups` - `int access(const char *path, int mode);`: 確認權限 - mode bit: - R_OK, W_OK, X_OK: read, write, exec permission - F_OK: file exist - `mode_t umask(mode_t cmask);`: mask 掉權限 - 直接用 umask 指令可以看到 touch 檔案時的預設權限 (被 mask 掉的數字) - 可以用 umask 指令改寫預設檔案權限 `umask 0` -> 預設所有權限都開 - 12-bit file permission - suid,sgid,sticky,9-bit permission - sticky bit - executable - cache 在 swap - 減少 loading 時間 - dir - delete or rename 的權限 - owner of file - owner of dir - superuser - ex: /tmp - file system - ![](https://i.imgur.com/GV08pTn.png) - i-node - file metadata - type - permission - data blocks - timestamps - reference counts - 通常為正整數 - 特別用途 - 0: reserved, or does not exist - 1: list of bad/defective blocks - 2: root directory of a partition - 兩個 dir 可以指向同一個 i-node - ![](https://i.imgur.com/gAhDLc3.png) - create dir - ![](https://i.imgur.com/rFbGrA4.png) - ![](https://i.imgur.com/rZ9tpIE.png) - reference counts - 指向 i-node 的 pointer 個數 - 增加 - link - hard link (必須在同一個 partition) - 減少 - unlink - symbolic link (soft link) - 大小為 target name 的長度 - 小心迴圈 - soft link 是可以指向不存在的檔案,但 hard link 不可 - ![](https://i.imgur.com/Tmin7Lj.png) - symlink - 建 symbolic link - target 和 link 可以在不同 file system - readlink - read target pathname - 結合 open, read and close - file time - ![](https://i.imgur.com/1tNc3kn.png) - ![](https://i.imgur.com/laANFlv.png) - utime - change access and modification time - directory operation - `void rewinddir(DIR *dir)` - reset pointer 到 dir stream 的開始 - `off_t telldir(DIR *dir)` - dir stream 現在的位置 - `void seekdir(DIR *dir, off_t offset)` - device special file - `dev_t` device number - major - device driver - minor - specific sub device - `st_dev` - `st_rdev` - created by `mknod` or auto generated when dev register - `hdaN?`、`sdaN?`、`scdN`、`ttyN`、`ttySN`、`pts/N`、`null`、`zero`、`random` ## sysinfo

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully