<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>All Posts - Wandering World</title>
        <link>http://chinyu1229.github.io/posts/</link>
        <description>All Posts | Wandering World</description>
        <generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>chinyu0916@gmail.com (Chinyu)</managingEditor>
            <webMaster>chinyu0916@gmail.com (Chinyu)</webMaster><copyright>This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.</copyright><lastBuildDate>Mon, 15 Nov 2021 15:20:12 &#43;0800</lastBuildDate><atom:link href="http://chinyu1229.github.io/posts/" rel="self" type="application/rss+xml" /><item>
    <title>Golang - 並行開發 --- Mutex</title>
    <link>http://chinyu1229.github.io/2021-11-15-golang_%E4%B8%A6%E8%A1%8C%E9%96%8B%E7%99%BC/</link>
    <pubDate>Mon, 15 Nov 2021 15:20:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-11-15-golang_%E4%B8%A6%E8%A1%8C%E9%96%8B%E7%99%BC/</guid>
    <description><![CDATA[Golang 並行（concurrent）開發 共享資源訪問控制 Mutex 結構 1 2 3 4  type Mutex struct{ state int32 sema uint32 }   state紀錄Mutex的四種狀態：主要兩個為Locked:表示是否被鎖定、Waiter:表示blocked中且等待拿鎖的goroutine數量
Method Lock()：加鎖 Unlock()：解鎖
加鎖過程：
 去判斷Locked值是否為0，若是0，把Locked set為1，代表拿到鎖 若是1，Waiter的值+1，並且此goroutine blocked 直到 Locked == 0才會被喚醒  解鎖過程：
 若沒有其他goroutine blocked，只要把Locked set 為 0，不需要釋放 semaphore 若有其他blocked goroutine，首先先把Locked set 為 0，然後查看到Waiter&gt;0，釋放一個 semaphore，喚醒一個blocked goroutine，被喚醒的goroutine把Locked set 為1  自旋 lock時，如果Locked為1，嘗試lock的goroutine不是馬上進入blocked，而是會持續地(時間很短)探測Locked是否為0，好處是可以避免goroutine的切換
 相當於CPU的PAUSE指令，過程中會持續探測Locked（與sleep不同的是不需要將goroutine轉成睡眠狀態） 自旋要滿足  自旋次數夠小，通常設定為4 CPU核心數&gt;1 scheduler 的可運行queue必須為空    也就是CPU不忙的時候啟用自旋
問題： 如果自旋過程中獲得鎖，避免了goroutine切換，那之前被blocked的goroutine很難獲得鎖，造成starving 因此新版的go新增了Mutex &ndash; starving欄位]]></description>
</item><item>
    <title>Golang - 平行開發</title>
    <link>http://chinyu1229.github.io/2021-11-05-golang_%E5%B9%B3%E8%A1%8C/</link>
    <pubDate>Fri, 05 Nov 2021 19:20:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-11-05-golang_%E5%B9%B3%E8%A1%8C/</guid>
    <description><![CDATA[Golang 平行(parallel) 簡介 平行(parallel)與並行(concurrent) 在執行一些需要快速計算的程式時，我們希望盡量使用CPU的多核心特性來將task平行（parallel）化，因此要分解計算任務到多個goroutine中平行運行，再合併各goroutine結果到最終result
並行(concurrent) 是一種程式架構的概念，將程式拆開成多個可以獨立運行的任務，concurrent可能會用到parallel。也就是說，concurrent可以讓很多事情一起做，但是“不一定”要真的在同一個“時間點”做。
Parallelism 注重規劃，將能夠concurrent的程式，分配給不同硬體單元，使其同時執行。 &mdash;&gt; 多核心使用
goroutine 多核 在平時直接使用 go func()創建goroutine，並使用top指令觀察，你會發現跟C語言中thread不同的是，go語言只會在某一個核心中呈現busy狀態。
 更新：目前新版的go語言的goroutine不需要設置runtime.GOMAXPROCS()會自動幫你判斷能用的核心數  因此在go語言中需要使用runtime.GOMAXPROCS(cpus)來開啟多核心模式，cpus不能超過原本電腦的核心數 在go語言中可以利用runtime.NumCPU()獲取你電腦CPU的核心數
範例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27  func sum(seq int, ch chan int) { defer close(ch) sum := 0 for i := 1; i &lt;= 10000000; i++ { sum += i } fmt.]]></description>
</item><item>
    <title>Link List in C</title>
    <link>http://chinyu1229.github.io/2021-09-10-linklist/</link>
    <pubDate>Fri, 10 Sep 2021 19:00:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-09-10-linklist/</guid>
    <description><![CDATA[Link List 基本概念  相同結構的東西（用struct)使用指標（pointer)串起來，相同結構的東西稱作NODE 在加入/刪除比array上好操作 有需要的時候才動態的配置空間(malloc / new) 查詢時比array慢  圖示：
靜態配置：
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29  #include&lt;stdio.h&gt;#include&lt;stdlib.h&gt; struct node{ int data; struct node *next; }; typedef struct node Node; int main() { Node x, y, z; Node *ptr = &amp;x; x.data = 10; x.]]></description>
</item><item>
    <title>Linux Chapter 25 ProcessTermination</title>
    <link>http://chinyu1229.github.io/2021-09-09-linux_chapter_25_processtermination/</link>
    <pubDate>Thu, 09 Sep 2021 21:13:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-09-09-linux_chapter_25_processtermination/</guid>
    <description><![CDATA[Process Termination _exit() and exit() 有兩種方式可以終止程式：
 abnormal - 由訊號觸發，預設是終止程式（可以core dump) normally - 使用_exit()終止程式  1 2  #include&lt;unisted.h&gt;void _exit(int status);    status:定義終止狀態，在parent process可以呼叫wait()以取得狀態 結束狀態為 0 ，表示process順利結束。非0表示異常終止 非0狀態沒有固定規則，每個應用程式有自己的規則要參考他們的文件 普遍為SUSv3制訂的：EXIT_SUCCESS(0) EXIT_FAILURE(1)  程式通常不會直接呼叫_exit()，因為會直接終止，通常會呼叫exit()，因為可以在真正呼叫_exit()前執行一些動作
1 2  #include&lt;stdlib.h&gt;void exit(int status);   會進行以下動作：
 以反向註冊順序，呼叫exit處理常式 flush stdio的串流緩衝區 使用status 提供的值執行_exit() system call  與在main() 中return 終止程式或執行到main()結尾終止的方式，return n; 等同於 exit(n)
 不等價的時候：若在exit的過程中有任何步驟存取main()的區域函數時，從main return會產生不可預期的行為。例如在呼叫setvbuf() 或 setbuf()時使用main()的區域函數時就會發生不等價的情況  行程終止的動作  關閉open file descriptor、directory stream、message catalog descriptor、conversion descriptor 關閉open file descriptor 後，會釋放此形成所有的file lock 解除任何加載的System V共享記憶體段，並將每個區段對應的shm_nattchcounter減去1 解除行程使用mmap()建立的記憶體映射   Exit Handler 在行程終止前執行一些操作，以應用程式的函式庫來說，行程終止前需要清理在生命週期間有用到的函式庫，因此需要exit handler來保證在終止前（結束時）會清理]]></description>
</item><item>
    <title>整數二分法 Binary Search</title>
    <link>http://chinyu1229.github.io/2021-9-7-%E4%BA%8C%E5%88%86%E6%B3%95/</link>
    <pubDate>Tue, 07 Sep 2021 23:11:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-9-7-%E4%BA%8C%E5%88%86%E6%B3%95/</guid>
    <description><![CDATA[整數二分 何時使用 有單調性（monotone)的一組數字可以二分，但沒有單調性也可以使用二分法
在何時適用 若可以找到某種性質，在右半邊滿足，左半邊不滿足(在右半邊不滿足，左半邊滿足)，就可以尋找邊界
模板code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  bool check(int x){/*stasify some conditions*/} // [l, r] -&gt; [l, mid] + [mid + 1, r] int bsearch1(int l, int r) { int mid = l + r &gt;&gt; 1; if(check(mid)) r = mid; else l = mid + 1; } // [l, r] -&gt; [l, mid - 1] + [mid, r] int bsearch2(int l, int r) { int mid = l + r + 1 &gt;&gt; 1; if(check(mid)) l = mid; else r = mid - 1; } return l; //also can return r   圖例與解釋 找尋紅色的邊界：check(mid) ：滿足紅色條件]]></description>
</item><item>
    <title>KMP算法 -- next解釋</title>
    <link>http://chinyu1229.github.io/2021-07-13-kmp%E7%AE%97%E6%B3%95/</link>
    <pubDate>Tue, 13 Jul 2021 17:40:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-07-13-kmp%E7%AE%97%E6%B3%95/</guid>
    <description><![CDATA[KMP 基本概念 一種用來字符串匹配的算法 一些定義：
 s[] 為主字串 ， p[] 是匹配串 ， 即可以理解成p是否是s的子字串 前綴：包含首位字符但不包含末位字符的子字串; 後綴：包含末位字符但不包含首位字符的子字串 部分匹配值 ： 前綴與後綴最長共有長度 next[] 存的是每個下標對應的部分匹配值   核心思考：每次匹配失敗時，把p串往後移動至next對應的值  next的含義與模擬 字串從1開始存，next[i], 是p[1,i]中前綴和後綴相同的最大長度（部分匹配值）， 定義 next[1] = 0 例如：
1 2 3  idx 1 2 3 4 5 6 str a b c a b a next 0 0 0 1 2 1   求next陣列的code
1 2 3 4 5 6 7  // m 為 p 的長度 for(int i = 2, j = 0; i &lt;= m; i++) { while(j &amp;&amp; p[i] !]]></description>
</item><item>
    <title>Linux Chapter 24 CreateProcess</title>
    <link>http://chinyu1229.github.io/2021-06-20-linux_chapter_24_createprocess/</link>
    <pubDate>Sun, 20 Jun 2021 17:13:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-06-20-linux_chapter_24_createprocess/</guid>
    <description><![CDATA[CreateProcess fork() exit() wait() execev() 簡介  fork()  parent process經由呼叫fork()建立一個 child process child獲得parent的stack segment、data segment、heap segment、text segment 可說是把parent process一分為二   exit()  terminate a process 將佔用的所有資源歸還給kernel parent 可以利用 wait()來取得結束的狀態(status)   wait()  若child process還未呼叫exit()，那wait()會suspend parent process，直到有任一child process terminated 可以取得status   execve()  Load a new program到目前process的記憶體 丟去現存的text segment 重新建立 stack segment、data segment、heap segment    大致流程圖
fork() 1 2 3  #include &lt;unistd.h&gt;pid_t fork(void); In parent: returns process ID of child on success, or –1 on error; in successfully created child: always returns 0    呼叫後將存在兩個process，且每個process都會從fork()的返回處繼續執行 兩個process擁有不同的stack segment、data segment、heap segment、text segment副本（child可以再修改，且不影響parent） 返回pid == 0是child process 返回pid !]]></description>
</item><item>
    <title>Backpack_Problem</title>
    <link>http://chinyu1229.github.io/2021-06-11-backpack-problem/</link>
    <pubDate>Thu, 10 Jun 2021 00:48:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-06-11-backpack-problem/</guid>
    <description><![CDATA[Backpack 0 - 1 Problem  主問題：從n個物品選一些物品，在不超過最大容量下，使得價值最大。 解空間：{x1,x2&hellip;.,xn}  xi : 0 or 1 (表示取或不取) 共有 $2^n$ 可能的解   限制條件： $\sum_{i=1}^n$ $w_ix_i$ &lt;= W 採用回溯法 限界條件：  對於任何一個中間節點z，從root到z的分支所代表的狀態已經確定，從z到子孫的節點還未確定。如果z在第t層，說明第1種物品到t-1種物品（是否裝入背包）確定，t可以沿著分支擴展確認狀態，t+1到n不確定。 目前裝入背包的物品總價用cp表示，因為還不確定t+1到n物品的狀態，先假設全部都放入背包，也就是剩餘的總價值，用rp表示。 cp + rp是所有從root出發經過中間節點z的可行解的價值上界。如果價值上界小於或等於目前的最優值，則說明節點z沒有繼續搜尋的必要 即 cp + rp &gt; bestp    solution 假設有4個物品，每個物品w [2,5,4,2], 價值v [6,3,5,4], W = 10
 初始化：sumw , sumv 統計所有物品的總重和總價 -&gt; sumw = 13, sumw = 18,目前放入背包的物品重量cw = 0, 總價cp = 0, 最優值 bestp = 0 第一層：t = 1,   判斷cw + w[1] = 2 &lt; W （滿足限制條件）向左擴展分支，令x[1] = 1, cw = cw + w[1] = 2, cp = cp+v[1] = 6，生成2好節點]]></description>
</item><item>
    <title>Linux Chapter 21 Signal 處理常式</title>
    <link>http://chinyu1229.github.io/2021-06-02-linux_chapter_21_signal%E8%99%95%E7%90%86%E5%B8%B8%E5%BC%8F/</link>
    <pubDate>Wed, 02 Jun 2021 22:10:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-06-02-linux_chapter_21_signal%E8%99%95%E7%90%86%E5%B8%B8%E5%BC%8F/</guid>
    <description><![CDATA[Linux Chapter 21 Signal 處理常式 訊號處理常式設計  設定一個全域flag，接著離開。主程式會週期性的檢測此flag，若有被設定為flag，會進行適當的反應 會做出幾種類型的清理動作，接著結束行程或使用非區域跳躍（nonlocal goto）解開unwind the stack，並將控制權交回給主程式（是先定義的位置）  可重入函式與非同步訊號安全函式 可重入與不可重入 訊號處理常式與multiple thread的概念有關，前者可能會在任意時間點非同步的中斷程式執行，所以主程式與訊號處理常式會變成在同一個行程中，2個獨立的thread(非同步執行) 若函式可以在同一個行程的各thread中同步且安全的執行，此函式稱為是可重入的（reentrant）
 SUSv3對可重入的定義是: 當兩條或多條thread呼叫函式時，即便是彼此互相交叉執行，也能保證效果與各thread以未定義順序呼叫時一致  若函式會更新全域或靜態的資料結構，可能就是不可重入的函式（只使用local變數的函式保證是可重入）。
 可能發生的情況： 若主程式在呼叫malloc()期間，受到一個同樣呼叫malloc()的訊號處理常式中斷，則此linklist可能會遭到破壞，因此malloc()的函式家族與使用這些函式的其他函式庫函式都是不可重入。 其他會傳回靜態配置的記憶體，也是不可重入的，crypt() getpwnam() gethostbyname() getservbyname() 函式的內部紀錄是使用靜態的資料結構也是不可重入的，例如scanf() printf()，他們會有緩衝的I/O更新內部資料結構，所以在訊號處理常式使用printf()也在主程式呼叫printf()，緩衝區的資料會交錯，導致得到非期望的輸出結果，甚至是整個程式crush  標準的非同步訊號安全函式（async-signal-safe functions）  指可以安全地從訊號處理常式進行呼叫。 當函式是reentrant函式，或是不會受到訊號處理常式中斷，可以稱函式為async-signal-safe function man page: https://man7.org/linux/man-pages//man7/signal-safety.7.html  在訊號處理常式內使用errno 因為可能會更新errno變數，會導致函式reentrant，因為可能會覆寫主程式之前呼叫函式設定的errno值。 所以可以先儲存errno的值，並在函式執行完畢之後，回存errno
1 2 3 4 5 6 7  void handler(int sig) { int sErrno; sErrno = errno; /* can execute a function that might modify errno */ errno = sErron; }   全域變數與sig_atomic_t資料型別 全域變數有reetrant問題，但有時需要在主程式與訊號處理常式之間共用全域變數，要能正確處理即可以保證安全。 常見的設計是：]]></description>
</item><item>
    <title>Linux Chapter 20 Signal 基本概念</title>
    <link>http://chinyu1229.github.io/2021-05-29-linux_chapter_20_signal-%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/</link>
    <pubDate>Sat, 29 May 2021 23:10:12 &#43;0800</pubDate>
    <author>Author</author>
    <guid>http://chinyu1229.github.io/2021-05-29-linux_chapter_20_signal-%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/</guid>
    <description><![CDATA[Linux Chapter 20 Signal 基本概念 概念 signal 可以通知行程（process）有事件發生，也可以稱為軟體中斷，多數情況下都無法預測訊號抵達的時間。
行程可以送出訊號給另外一個行程，在此可以做為synchronization 或者 IPC 的技術。
訊號類型與預設行為 可以在signal(7)使用手冊列出訊號名稱，或是參考書上p.430 下圖列出簡易版訊號表： 改變訊號處置 Unix系統提供兩種 1.signal() 2. sigaction()
 signal()提供設定訊號的原始API 介面比sigaction()簡單 sigaction()是建立訊號處置常式首推的API signal() 是基於 sigaction()實作的函式  1 2 3  #include&lt;signal.h&gt;void (*signal(int sig, void (*handler)(int))); Return previous signal disposition on success,or SIG_ERR on error    handler可以用以下的值取代  SIG_DFL:將訊號處置 重新設定為預設值，適用於還原先前signal()呼叫改變的訊號處置 SIG_IGN:忽略該訊號，行程也不會知道有此訊號    訊號處理常式 範例：
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  #include&lt;signal.]]></description>
</item></channel>
</rss>
