你好,我是 Yama,歡迎來到我的網站。
Contact Me
- Email: [email protected]
- GitHub: @9501sam
題目連結:17. Letter Combinations of a Phone Number 我覺得這種 backtracking 或是 dfs 的題目都需要想清處 depth 的定義是什麼,想清楚就會好寫許多。 程式實做 class Solution { public: vector<string> letterCombinations(string digits) { if (digits.size() == 0) return {}; vector<string> phoneNumber = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" }; vector<string> combs; string current; backtracking(0, digits, current, phoneNumber, combs); return combs; } void backtracking(int index, string digits, string current, vector<string> phoneNumber, vector<string> &combs) { if (index >= digits.size()) { combs.push_back(current); return; } int i = digits[index] - '0'; for (char c : phoneNumber[i]) { current.push_back(c); backtracking(index + 1, digits, current, phoneNumber, combs); current.pop_back(); } } };
Lab 連結: Lab: Xv6 and Unix utilities Boot xv6(Easy) 題目敘述: 這部份的詳細內容都寫在 lab util 中,會需要一個 linux 系統(windows使用者可以用虛擬機),Xv6 會跑在 linux 所架設的虛擬機上。 下載原始碼 git clone git://g.csail.mit.edu/xv6-labs-2022 cd xv6-labs-2022 安裝架設虛擬機的套件 我自己是用 Debian,如果你用的是 ubuntu 的話下載步驟應該也是一樣的,至於是其他系統的使用者,可以看這裡 sudo apt-get install git build-essential gdb-multiarch qemu-system-misc gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu compile程式碼並且讓他跑在虛擬機上 $ make qemu ... (一大串訊息) ... xv6 kernel is booting hart 2 starting hart 1 starting init: starting sh $ 到這裡,Xv6已經成功開機了! 嘗試打個指令 $ ls . 1 1 1024 .. 1 1 1024 README 2 2 2059 xargstest.sh 2 3 93 cat 2 4 24120 echo 2 5 22944 forktest 2 6 13184 grep 2 7 27424 init 2 8 23680 kill 2 9 22904 ln 2 10 22744 ls 2 11 26312 mkdir 2 12 23040 rm 2 13 23032 sh 2 14 41856 stressfs 2 15 23904 usertests 2 16 148312 grind 2 17 38008 wc 2 18 25232 zombie 2 19 22280 console 3 20 0 沒意外的話,會出現以上的畫面 ...
題目連結:206. Reverse Linked List 解題思路 這題還蠻直接的,把 Linked List 給掃過一遍,並且一個一個的把指標顛倒過來。 剛開始的時候我用了這個寫法: class Solution { public: ListNode* reverseList(ListNode* head) { if (!head) return head; ListNode *slow = head; ListNode *fast = head->next; while (fast != nullptr) { ListNode *nextNode = fast->next; fast->next = slow; slow = fast; fast = nextNode; } slow->next = nullptr; return slow; } }; 但這個寫法是錯誤的,因為 slow 從 head 開始的話,最一開始的 head 沒有指向 nullptr,所以需要把 slow 從 nullptr 開始會比較好。 我學到的是面對到 Edge Case 時,要特別小心注意才行。 程式碼 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { ListNode *slow = nullptr; ListNode *fast = head; while (fast != nullptr) { ListNode *nextNode = fast->next; fast->next = slow; slow = fast; fast = nextNode; } return slow; } };
如何建立一個免費的 vm 根據 google cloud 的說明 https://cloud.google.com/free?hl=en 滿足以下條件的 vm 是可以不用收錢的 1 non-preemptible e2-micro VM instance per month in one of the following US regions: Oregon: us-west1 Iowa: us-central1 South Carolina: us-east1 30 GB-months standard persistent disk 1 GB of outbound data transfer from North America to all region destinations (excluding China and Australia) per month 因此等等在建立 vm 時,按照上面的條件建立,並且要注意的是建立兩個以上的 vm 還是要收錢的,免費的只有第一個 建立 vm 步驟 首先你會先需要建立一個 google cloud 帳號 在 compute engin 中,點選上方的 “Create Instance” ...
Lab 連結: Lab: system calls 大綱 xv6 有哪些 system call,以及他們的作用為何 ? 以程式碼的觀點來理解 xv6 的 system call 流程 Using gdb System call tracing 1. xv6 有哪些 system call,以及他們的作用為何 ? 0. kernel/syscall.h 定義 syste mcall 的編號 // System call numbers #define SYS_fork 1 #define SYS_exit 2 #define SYS_wait 3 #define SYS_pipe 4 #define SYS_read 5 #define SYS_kill 6 #define SYS_exec 7 #define SYS_fstat 8 #define SYS_chdir 9 #define SYS_dup 10 #define SYS_getpid 11 #define SYS_sbrk 12 #define SYS_sleep 13 #define SYS_uptime 14 #define SYS_open 15 #define SYS_write 16 #define SYS_mknod 17 #define SYS_unlink 18 #define SYS_link 19 #define SYS_mkdir 20 #define SYS_close 21 2. 以程式碼的觀點來理解 xv6 的 system call 流程 以下使用 user/cat.c 為例,來探討 xv6 的 system call 流程,流程中有 3 大步驟 ...
取得 domain 架設網站需要先註冊一個 domain, 這裡我使用的是 Cloudflare, 註冊好一個 domain 之後,在 DNS > Records 的地方新增一個 Record Type: A name: yamatrail.com IPv4 Address: 填入 vm 的 IP (在 google cloud 上取得) 這會告訴他當其他人在瀏覽器中輸入 yamatrail.com 時,會導到我們先前在 google cloud 上所建立的 vm 在 Cloudflare 產生憑證 登入您的 Cloudflare 儀表板,選擇 yamatrail.com。 點擊左側選單的 SSL/TLS,然後選擇 Origin Server (源伺服器) 子分頁。 點擊「Create Certificate」按鈕。 保持預設選項(私鑰類型 RSA,憑證有效期 15 年),直接點擊最下方的「Create」。 這是最關鍵的一步:Cloudflare 會顯示兩個大框框的文字,分別是 Origin Certificate 和 Private Key。 請立刻將這兩段文字完整複製出來,並分別儲存到您本地筆電的兩個純文字檔案中: 將 Origin Certificate 的內容存為 yamatrail.com.pem。 將 Private Key 的內容存為 yamatrail.com.key。 注意:Private Key 只會顯示這一次,關閉頁面後就再也看不到了! 之後就可以在 vm 上安裝並設定 nginx 了,在這之前可以先檢查 vm 的設定是否有允許 HTTP 及 HTTPS 連線 ...
當我們設定好 vm 之後,先回到我們工作用的電腦,以我自己來說,這會是我的筆電。 我們的網站編輯與開發都會在這台筆電上,下一篇文章才會說明如何把網站內容部署到 vm 中, 總之,這篇文章的內容都在個人的筆電(或 PC)上操作。 安裝套件 sudo apt update && sudo apt upgrade -y sudo apt install nginx git -y wget https://github.com/gohugoio/hugo/releases/download/v0.146.0/hugo_extended_0.146.0_linux-amd64.deb sudo dpkg -i hugo_extended_0.146.0_linux-amd64.deb hugo version 在筆電上先使用 hugo 建立一個 repo 出來,並且使用 git 做版控,然後推到自己的 github 上 hugo new site yamatrail-site cd yamatrail-site git init git add . git commit -m "Init commit" 使用這個指令可以新增一篇文章: hugo new content posts/hello-world.md vim content/posts/hello-world.md 設定 theme 這裡可先在 Hugo Themes 看看,再決定自己要用的主題,我自己用的是 PaperMod ...
建立網站部署流程 總流程概覽 我這裡的部署流程為:大多數的檔案編輯都在我的筆電上,檔案修改完之後推到 github 上,利用 github action 自動部署到 vm 當中。 ssh key 的準備:在筆電和 VM 之間建立一對專門用於自動化部署的 SSH Key,讓 GitHub Actions 才有權限可以登入 vm 中。 設定 GitHub Repo:將 SSH 私鑰和伺服器資訊,以加密的方式儲存在 github repo 中的 Secrets 中。 建立 GitHub Actions Workflow:撰寫 .github/workflows/deploy.yaml 設定檔,這會告訴 github 該做些什麼把網站內容放到 vm 中。 觸發與驗證:將程式碼 git push 到 GitHub,觸發自動化流程,檢查流程是否正確。 階段一:準備工作 - 建立 SSH 信任關係 步驟 1:「筆電」上產生一對 SSH Key 在筆電上: # -t ed25519: 使用更現代、更安全的加密演算法 # -C "..." : 註解,方便你辨識這對 Key 的用途 # -f ~/.ssh/hugo_deploy_key: 指定金鑰檔案的路徑與名稱,避免覆蓋你現有的 id_rsa 或其他金鑰 ssh-keygen -t ed25519 -C "GitHub Actions for yamatrail.com" -f ~/.ssh/hugo_deploy_key 執行之後,會在 ~/.ssh/ 中產生公鑰與私鑰 ...
xv6 中的 virtual memory memory layout 每一個 process 都會有自己的一個 page table,kernel 則是有它自己獨立的一個 page table 一般來說 kernel page table 會 map 所有的 physical address,這樣在 kernel mode 的時候就可以針對所有 pa 做動作 Kernel address space 接著依序講解 MAXVA, PHYSTOP, KERNBASE MAXVA 如同先前提及,在 Sv39 中 virtual address 由 39 bits 組成 // kernel/riscv.h // one beyond the highest possible virtual address. // MAXVA is actually one bit less than the max allowed by // Sv39, to avoid having to sign-extend virtual addresses // that have the high bit set. #define MAXVA (1L << (9 + 9 + 9 + 12 - 1)) 最大的 virtual address MAXVA 是 0b100 0000 0000 0000 0000 0000 0000 0000 0000 0000(38 0s): 可以得知 Sv39 並沒有把 39 個 bits 用滿,實際上最大的 address 只會到 MAXVA - 1 = 0b011 1111 1111 1111 1111 1111 1111 1111 1111 1111 = 0x3fffffffff ...
Lab 連結: lab pgtbl Speed up system calls (easy) 題目敘述: When each process is created, map one read-only page at USYSCALL (a virtual address defined in memlayout.h). At the start of this page, store a struct usyscall (also defined in memlayout.h), and initialize it to store the PID of the current process. For this lab, ugetpid() has been provided on the userspace side and will automatically use the USYSCALL mapping. You will receive full credit for this part of the lab if the ugetpid test case passes when running pgtbltest. ...