Time of Update: 2018-12-03
條件變數分為兩部分: 條件和變數. 條件本身是由互斥量保護的. 線程在改變條件狀態前先要鎖住互斥量. 1. 初始化: 條件變數採用的資料類型是pthread_cond_t, 在使用之前必須要進行初始化, 這包括兩種方式:靜態: 可以把常量PTHREAD_COND_INITIALIZER給靜態分配的條件變數.動態: pthread_cond_init函數, 是釋放動態條件變數的記憶體空間之前,
Time of Update: 2018-12-03
互斥量從本質上說就是一把鎖, 提供對共用資源的保護訪問. 1. 初始化: 在Linux下, 線程的互斥量資料類型是pthread_mutex_t. 在使用前, 要對它進行初始化:對於靜態分配的互斥量, 可以把它設定為PTHREAD_MUTEX_INITIALIZER, 或者調用pthread_mutex_init.對於動態分配的互斥量, 在申請記憶體(malloc)之後, 通過pthread_mutex_init進行初始化,
Time of Update: 2018-12-03
1. 概念: 線程與進程是不同的, 準確地說, 進程可以由多個線程組成, 線程是進程的組成元素. 預設情況下, 一個進程只是由一個線程構成, 它串列執行該進程要執行的任務. 多線程情況下, 每個線程執行各自的任務, 它們之間更多是並行的. 線程的作用具體有:在單進程環境中執行多個任務.共用該進程的組成組件, 如檔案描述符和記憶體, 但需要較為複雜的機制.同步和非同步執行.線程改善輸送量, 由串列轉化為並行,
Time of Update: 2018-12-03
1. 下面介紹list的插入函數:#ifndef CONFIG_DEBUG_LISTstatic inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next){ next->prev = new; new->next = next; new->prev = prev;
Time of Update: 2018-12-03
《The C Programing Language》K&R 經典的C語言程式設計教材,作者是C語言的發明者,教材內容深入淺出。雖然有點老,但是必備的一本手冊,現在有時候我還常翻翻。篇幅比較小,但是每看一遍,就有一遍的收穫。另外也可用譚浩強的《C語言程式設計》代替。 《Advanced Programing in Unix Envirement》 W.Richard
Time of Update: 2018-12-03
這是線程級的清理處理, 類似於進程級的atexit, 這在前面的進程環境和進程式控制制系列文章中有過比較詳細的介紹.1. 觸發清理程式的3個條件:調用pthread_exit時.響應取消請求時.用非0的execute參數調用pthread_cleanup_pop時. 2. pthread_cleanup_push函數:原型: void pthread_cleanup_push(void (*rtn)(void *), void *arg);標頭檔:
Time of Update: 2018-12-03
這篇文章介紹守護進程的概念, 結構, 編寫守護進程以及報告進程錯誤狀況. 1. 概念:守護進程又稱為精靈進程(daemon), 是存留時間比較長的一種進程. 它們常常在系統自舉時啟動, 僅在系統關閉時才終止. 因為它們沒有控制終端, 所以說它們是在後台啟動並執行. 先來介紹一些Linux系統常見的守護進程:init: 它的pid為1, 是系統守護進程, 負責啟動系統服務, 這些服務通常自己也擁有守護進程.keventd: 為在核心中運行計劃執行的函數提供進程上下文.kapmd:
Time of Update: 2018-12-03
眾所周知,Linux動態庫的預設搜尋路徑是/lib和/usr/lib。動態庫被建立後,一般都複製到這兩個目錄中。當程式執行時需要某動態庫,並且該動 態庫還未載入到記憶體中,則系統會自動到這兩個預設搜尋路徑中去尋找相應的動態庫檔案,然後載入該檔案到記憶體中,這樣程式就可以使用該動態庫中的函數,以及 該動態庫的其它資源了。在Linux 中,動態庫的搜尋路徑除了預設的搜尋路徑外,還可以通過以下三種方法來指定。方法一:在設定檔/etc/ld.so.conf中指定動態庫搜尋路徑。
Time of Update: 2018-12-03
介紹一些list的iterate over函數:1. #define list_for_each(pos, head) / for (pos = (head)->next; prefetch(pos->next), pos != (head); / pos = pos->next)關於這個遍曆的迴圈似乎沒什麼好說的, 從head->next開始, 用next指標遍曆, prefetch的是將指標推入CPU L1
Time of Update: 2018-12-03
線上程同步系列的第一篇文章裡已經說過, 讀寫鎖是因為有3種狀態, 所以可以有更高的並行性.1. 特性: 一次只有一個線程可以佔有寫入模式的讀寫鎖, 但是可以有多個線程同時佔有讀模式的讀寫鎖. 正是因為這個特性,當讀寫鎖是寫加鎖狀態時, 在這個鎖被解鎖之前, 所有試圖對這個鎖加鎖的線程都會被阻塞.當讀寫鎖在讀加鎖狀態時, 所有試圖以讀模式對它進行加鎖的線程都可以得到訪問權, 但是如果線程希望以寫入模式對此鎖進行加鎖, 它必須阻塞知道所有的線程釋放鎖.通常,
Time of Update: 2018-12-03
Linux提供了記憶體映射函數mmap, 它把檔案內容映射到一段記憶體上(準確說是虛擬記憶體上), 通過對這段記憶體的讀取和修改, 實現對檔案的讀取和修改, 先來看一下mmap的函式宣告:標頭檔:<unistd.h> <sys/mman.h> 原型: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize); 傳回值: 成功則返回映射區起始地址,
Time of Update: 2018-12-03
1. 前言:有的程式可以通過編譯, 但在運行時會出現Segment fault(段錯誤). 這通常都是指標錯誤引起的.但這不像編譯錯誤一樣會提示到檔案->行, 而是沒有任何資訊, 使得我們的調試變得困難起來.2. gdb:有一種辦法是, 我們用gdb的step, 一步一步尋找. 這放在短小的代碼中是可行的, 但要讓你step一個上萬行的代碼, 我想你會從此厭惡程式員這個名字, 而把他叫做調試員.我們還有更好的辦法, 這就是core file.3.
Time of Update: 2018-12-03
Linux的訊息佇列(queue)實質上是一個鏈表, 它有訊息佇列標識符(queue ID). msgget建立一個新隊列或開啟一個存在的隊列; msgsnd向隊列末端添加一條新訊息; msgrcv從隊列中取訊息, 取訊息是不一定遵循先進先出的, 也可以按訊息的類型欄位取訊息. 1. 標識符(des)和鍵(key): 訊息佇列, 訊號量和共用儲存段, 都屬於核心中的IPC結構, 它們都用標識符來描述. 這個標識符是一個非負整數, 與檔案描述符不同的是,
Time of Update: 2018-12-03
1. alarm函數:alarm函數是設定一個計時器, 在計時器逾時的時候, 產生SIGALRM訊號. 如果不忽略或捕捉此訊號, 它的預設操作是終止調用該alarm函數的進程.原型如下:#include <unistd.h>unsigned int alarm(unsigned int seconds);返回0或餘留秒數說一下alarm的傳回值問題, 每個進程只能有一個alarm維護的"鬧鐘". 如果該"鬧鐘"順利逾時, 則返回0;如果該"鬧鐘"在計時過程中,
Time of Update: 2018-12-03
線程的同步, 發生在多個線程共用相同記憶體的時候, 這時要保證每個線程在每個時刻看到的共用資料是一致的. 如果每個線程使用的變數都是其他線程不會使用的(read & write), 或者變數是唯讀, 就不存在一致性問題. 但是, 如果兩個或兩個以上的線程可以read/write一個變數時, 就需要對線程進行同步, 以確保它們在訪問該變數時, 不會得到無效的值, 同時也可以唯一地修改該變數並使它生效. 以上就是我們所說的線程同步. 線程同步有三種常用的機制:
Time of Update: 2018-12-03
1. 函數說明:kill和raise是用來發送訊號的:kill把訊號發送給進程或進程組;raise把訊號發送給(進程)自身.他們的原型如下:#include <signal.h>int kill(pid_t pid, int signo);int raise(int signo);成功則返回0, 出錯則返回-1 從原型上可以看出, raise函數是可以通過kill實現的.raise(signo);等價於:kill(getpid(), signo);2.
Time of Update: 2018-12-03
在Linux中的list是系統通用鏈表,它廣泛應用在系統各個地方,如系統訊息佇列、進程列表等地。可以說,只要有表的地方,就會用到這個list。http://download1.csdn.net/down3/20070530/30164350798.h今天我們先解析一下跟初始化有關的代碼:1. 表頭結點結構struct list_head { struct list_head *next, *prev;};這和我們通常寫鏈表一樣,定義一個表頭結點。從next,
Time of Update: 2018-12-03
sigaction函數是用作檢查/修改與指定訊號相關聯的處理動作. 在UNIX早期版本中使用signal, 後來改用了sigaction, 可見它的功能比signal要強大. 另外, signal函數也是可以用sigaction實現的.1. sigaction原型:#include <signal.h>int sigaction(int signo, const struct sigaction *restrict act,
Time of Update: 2018-12-03
1. 定義:標頭檔: <asm/semaphore.h>資料類型: struct semaphore直接建立: void sema_init(struct semaphore *sem, int val); /* 其中val是訊號量的初始值 */輔助宏: DECLARE_MUTEX(name); /* 把一個稱為name的訊號量變數初始化為1 */DECLARE_MUTEX_LOCKED(name); /* 把一個稱為name的訊號量變數初始化為0 */動態分配:/*
Time of Update: 2018-12-03
進程部分介紹過了setjmp和longjmp函數, 這兩個函數在跳轉時會帶訊號屏蔽字跳轉, 在訊號處理常式(hanlder)中使用longjmp會導致後來產生的這種訊號被屏蔽.POSIX.1 也沒有具體說明setjmp和longjmp對訊號屏蔽字的作用, 而是定義了兩個新函數: sigsetjmp和siglongjmp.1.