linux用戶空間,內核空間鎖簡介,使用

關於內核狀態下的鎖和用戶空間的鎖的介紹可以參考以下連接:
https://blog.csdn.net/lilichang11106/article/details/84069357
主要內容可以描述如下:

內核鎖 用戶鎖
spinlock_t pthread_ spinlock_t
mutex_t pthread_mutex_t、pthread_rwlock_t
struct semaphore sem_t
rwlock_t pthread_ spinlock_t
pthread_cond_t

表格中每一行中的鎖功能類似,具體定義,數據結構,初始化方法,開閉方法如上文中連接所示。
本文將給出實際的代碼來實例如何使用鎖保護資源。
內核鎖的使用在內核驅動等模塊,進程調度處理進程列表,中斷下半部分任務列表等地方隨處可見,這裏就不做實例了。
首先我們來看看在linux用戶空間使用spin_lock:

#include<string>
#include<stdio.h>
#include<unistd.h>
#include<string.h>

#define TEST_USER_SPIN_LOCK


#ifdef TEST_USER_SPIN_LOCK
#include<pthread.h>

pthread_spinlock_t lock = 0;
int count = 0;

void* work(void* param)
{
 for (int i = 0; i < 3; i++)
 {
  printf("pt before lock.\n");
  pthread_spin_lock(&lock);
  ++count;
  //usleep(0);
  pthread_spin_unlock(&lock);
  printf("pt after lock.\n");
 }
 return NULL;
}

#endif

//#include "dervied.h"
int version=1;

int main()
{
#ifdef TEST_USER_SPIN_LOCK
 pthread_t pt = 0;
 pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
 pthread_create(&pt, NULL, work, NULL);
 
 for (int i = 0; i < 3; i++)
 {
  printf("main before lock.\n");
  pthread_spin_lock(&lock);
  ++count;
  usleep(10);
  pthread_spin_unlock(&lock);
  printf("main after lock.\n");
 }
 pthread_join(pt, NULL);
 pthread_spin_destroy(&lock);
#endif
	return 0;
}

以上代碼編譯運行結果如下:
main before lock.
pt before lock.
main after lock.
main before lock.
pt after lock.
pt before lock.
main after lock.
main before lock.
pt after lock.
pt before lock.
main after lock.
pt after lock.
可見,spin_lock已經起了作用。
上面的代碼中,我把pt trhread中的usleep(0);註釋掉了,感興趣朋友可以打開試一下。

thread_spinlock_t的特點是高效。但是如果一個線程在獲得spinlock的時候陷入操作系統內核(比如時間片超時、缺頁異常)會怎麼樣呢?另外一個線程在獲取spinlock的時候會一直佔用cpu。會有一個瞬間的cpu佔用率高峯?這個高峯的持續時間取決於另外一個線程何時從內核返回。當然,如果臨界區很小的話,這個衝突的機率也是很小的。但是使用pthread_mutex_t就不會有這個問題,代價是線程上下文切換的開銷。
以下代碼使用usleep(0)來模擬時間片超時的情況,證實了這個猜想是符合實際的。
另外,spinlock的還有一個實現上的特點是會鎖總線,降低系統吞吐量。對於內核來說,線程數就是核心/cpu數量,所以影響不大?但是對於應用程序來說,如果線程很多(>>cpu數量)而且衝突嚴重,會非常影響性能?

有時間再給大家展示別的鎖的使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章