守護進程:
daemon進程,通常運行於操作系統後臺,脫離控制終端。一般不與用戶直接交互。
週期性的等待某個事件發生或週期性執行某一動作。
不受用戶登錄註銷影響,通常採用以d結尾的命名方式
守護進程創建步驟:
1、fork子進程,讓父進程終止
2、子進程調用setsid()創建新會話
3、通常根據需要,改變工作目錄位置chdir() (防止目錄被卸載)
4、通常根據需要,重設umask文件權限掩碼 (影響新文件的創建權限)
5、通常根據需要,關閉/重定向 文件描述符
6、守護進程 業務邏輯。while()
線程概念:
進程:有獨立的 進程地址空間,有獨立的pcb。 分配資源的最小單位
線程:有獨立的pcb,沒有獨立的進程地址空間。
ps -Lf 進程Id ---->線程號。LWP --->cpu執行的最小單位。
線程共享:
獨享 棧空間(內核棧、用戶棧)
共享./text./data ./rodata ./bass heap -->全局變量
線程控制原語:
pthread_t pthread_self(void);
獲取線程id。線程id是在進程地址空間內部,用來標識線程身份的id號
返回值:本線程 id
檢查出錯返回:線程當中用
fprintf(stderr,"xxxxxx %s\n", strerror(ret));
pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_rountn)(void*), void *arg);
參數1:傳出參數,表新創建的子線程id
參數2:線程屬性,傳NULL表使用默認屬性
參數3:子線程回調函數,創建成功,pthread_create函數返回時,該函數會被自動調用
參數4:參3的參數,沒有的話,傳NULL
返回值:
成功:0
失敗:errno
循環創建N個子線程:
for(i=0;i<5;i++)
pthread_create(&tid, NULL, tfn, (void*)i); //將int類型i,強轉成void*,傳參
void pthread_exit(void* retval); 退出當前線程
retval:退出值,無退出值時,NULL
exit():退出當前進程
return:返回到調用者那裏去
pthread_exit():退出當前線程
int pthread_jion(pthread_t thread, void **retval); //回收線程
thread:待回收的線程iD
retval:傳出參數,回收的那個線程的退出值
返回值:
成功:0
失敗:errno
int pthread_detach(pthread_t thread) //設置線程分離
thread:待分離的線程id
返回值:
成功:0
失敗:errno
int pthread_cancel(pthread_t thread);//殺死一個線程,需要到達取消點(保存點)
thread:待殺死的線程id
返回值:
成功:0
失敗:errno
如果,子線程沒有到達取消點,那麼pthread_cancel無效
我們可以在線程中,手動添加一個取消點,使用pthread_testcancel();
成功被pthread_cancel 殺死的線程,返回 -1, 使用pthread_join回收
線程控制原語: 進程控制原語
pthread_create ->fork()
pthread_self ->getpid()
pthread_exit() ->exit()
pthread_join() ->wait/waitpid()
pthread_cancel() ->kill()
pthread_detach()
線程屬性:
設置分離屬性:
pthread_attr_t attr 創建一個線程屬性結構體變量
pthread_attr_init(&attr) 初始化線程屬性
pthread_attr_setdatachstate(&attr, PTHREAD_CARETE_DETACH);//設置線程屬性爲分離態
pthread_carete(&tid, &attr, tfn, NULL) 藉助修改的,設置線程屬性 創建爲分離態的新線程
pthread_attr_destory(&attr) 銷燬線程屬性
線程同步:
協同步調,對公共區域數據按序訪問,防止數據混亂,產生於時間有關的錯誤。
鎖的使用:
建議鎖!對公共數據進行保護。所有線程【應該】在訪問公共數據前先拿鎖再訪問,但 鎖本身不具備強制性
使用mutex(互斥鎖、互斥量)一般步驟:
1、pthread_mutex_lock:創建鎖
2、pthread_mutex_init:初始化
3、pthread_mutex_lock:加鎖
4、訪問共享數據
5、pthread_mutex_unlock:解鎖
6、pthread_mutex_destroy:銷燬鎖
初始化互斥量:
pthread_mutex_t mutex;
1、pthread_mutex_init(&mutex, NULL) 動態初始化
2、pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER 靜態初始化
注意事項:
儘量保證鎖的粒度,越小越好。(訪問共享數據前,加鎖;訪問結束後【立即】解鎖)
互斥鎖,本質是結構體。我們可以看成整數。初值爲1(pthread_mutex_init()函數調用成功)
加鎖:--操作,阻塞線程
解鎖:++操作,喚醒阻塞在鎖上的線程
try鎖:嘗試加鎖,成功--。失敗,返回。同時設置錯誤號EBUSY
restrict關鍵字:
用來限定指針變量,被該關鍵字限定的指針變量所指向的內存操作,必須由本指針完成
【死鎖】:
是使用鎖不恰當導致的現象:
1、對一個鎖反覆lock
2、兩個線程,各自持有一把鎖,請求另一把
讀寫鎖:
鎖只有一把, 以讀方式給數據加鎖--讀鎖。以寫方式給數據加鎖==寫鎖
讀共享,寫獨佔
寫鎖優先級高
相較於互斥量而言,當讀線程多的時候,提高訪問效率。
pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock, NULL);
pthread_rwlock_rdlock
pthread_rwlock_wrlock
pthread_rwlock_unlock
pthread_rwlock_destroy
條件變量:
本身不是鎖!但是通常結合鎖來使用(mutex)
pthread_cond_t cond;
初始化條件變量:
1、pthread_cond_init(&cond, NULL); 動態初始化
2、pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 靜態初始化
阻塞等待條件:
pthread_cond_wait(&cond, &mutex);
作用:
1)阻塞等待條件變量滿足
2)解鎖已經加鎖成功的信號量(相當於pthread_mutex_unlock(&mutex))
3)當條件滿足,函數返回時,重新加鎖信號量(相當於pthread_mutex_lock(&mutex))
pthread_cond_signal():喚醒阻塞在條件變量上的(至少)一個線程
pthread_cond_broadcast():喚醒阻塞在條件變量上的所有線程
【要求:能夠藉助條件變量,完成生產者消費者問題】
信號量:
應用於線程、進程間同步
相當於 初始化值爲N的互斥量。N值 表示可以同時訪問共享數據區的線程數
函數:
sem_t sem; 定義類型
int sem_init(sem_t *sem, int pshared, unsigned int value)
參數:
sem:信號量
pshared:0:用於線程間同步
1:用於進程間同步
value:N值(指定同時訪問的線程數)
sem_destroy();
sem_wait() 一次調用,做一次--操作,當信號量的值爲0時,再次--就會阻塞。(對比pthread_mutex_lock)
sem_post() 一次調用,做一次++操作,當信號量的值爲N是,再次++就會阻塞。(對比pthread_mutex_unlock)