Linux的一些學習筆記

2021-08-20 07:26:37 字數 3032 閱讀 8565

/*linux記憶體管理*/

實體地址是虛擬位址的子集(64位cpu定址64tb)

mmu將cpu發出的虛擬位址變為實體地址,交給記憶體匯流排(段式位址轉換,頁式位址轉換)

記憶體申請和釋放,kmalloc和kfree

static void *malloc(int size)//要申請size位元組大小的記憶體空間

static void free(void *where)//釋放記憶體空間

/*中斷*/

linux系統規定了中斷服務處理函式的引數和返回型別

三部曲:編服務,報名,允許中斷

irqreturn_t myfun_isr(int irq,void* dev_id)

int request_irq(unsigned int irq      , irq_handler_t handler,

unsigned long irqflags, const char *devname  , void *dev_id)

enable_irq(irq)

/*定時*/

硬體定時器:操作arm的暫存器,類似tcfgx,tcon,tcnt,tcmp

軟體定時器:

static struct timer_list my_timer;//定義乙個軟體定時器

struct timer_list ;  

void my_timer_function(...);//定義自己的軟體定時器函式

init_timer(&my_timer);

my_timer.function=my_timer_function;

add_timer(my_timer);

併發-多個執行緒同時訪問同乙個裝置驅動程式的共享資源

併發控制方式:訊號量 和 自旋鎖

訊號量:(互斥訊號量,計數訊號量)

struct semaphore sem;//定義乙個訊號量

struct semaphore ;  

void sema_init(struct semaphore * sem,int val);//初始化乙個訊號量,val=1,則變成互斥鎖mutex

void down(struct semaphore * sem);//獲取訊號量,可能導致程序睡眠,sem減1

void up  (struct semaphore * sem);//釋放訊號量,喚醒等待者,sem加1

自旋鎖:(自旋意味著原地打轉,只能乙個持有者)

spin_lock_init(x)//該巨集用於初始化自旋鎖x。自旋鎖在真正使用前必須先初始化。該巨集用於動態初始化。

spin_lock(lock)//該巨集用於獲得自旋鎖lock,如果能夠立即獲得鎖,它就馬上返回,

//否則,它將自旋在那裡,直到該自旋鎖的保持者釋放,這時,它獲得鎖並返回。

//總之,只有它獲得鎖才返回。

spin_trylock(lock)//該巨集盡力獲得自旋鎖lock,如果能立即獲得鎖,它獲得鎖並返回真,

//否則不能立即獲得鎖,立即返回假。它不會自旋等待lock被釋放。

spin_unlock(lock)//該巨集釋放自旋鎖lock,它與spin_trylock或spin_lock配對使用。

【區別】:訊號量試用於保持時間較長的情況,自旋鎖試用於較短的情況

訊號量可能會引起呼叫者睡眠,所以不能在中斷服務函式中使用訊號量

/*阻塞與非阻塞*/(站在應用程式的角度)

應用程式阻塞訪問裝置,裝置沒準備好,則應用程式進入掛起後的睡眠狀態

應用程式非阻塞訪問裝置,裝置沒準備好,則應用程式直接返回

每個裝置驅動都有乙個程序等待佇列(wait_queue),阻塞訪問時,若是裝置還沒有準備好,

就通過wait_event(為訪問裝置的程序而建立等待佇列的節點),將該程序加入到wait_queue中,

若是一會兒裝置準備好了,就呼叫wake_up喚醒阻塞的程序(喚醒哪個全靠mode?)。

//__wake_up(wait_queue_head_t *q, unsigned int mode, 

//          int nr_exclusive    , void *key)

【linux裝置驅動程式的阻塞程式設計】

1.定義乙個與驅動程式配對的程序等待佇列,並初始化(實質上只定義乙個等待佇列頭)

static wait_queue_head_t wait_queue;

init_waitqueue_head(&wait_queue);

2.在裝置讀操作中,呼叫 wait_event 實現阻塞訪問

3.在裝置寫操作中,呼叫 wake_up 喚醒該裝置等待佇列上的程序

/*非同步通知*/(橋梁)

非同步的出現是為了解決裝置驅動程式某個事件發生時,能夠及時通知應用程式,在核心空間(裝置驅動)

和使用者空間(應用程式)架起了通訊的橋梁。

struct   fasync_struct ;

//用fasync_helper建立乙個fasync_struct的結構體變數,將其初始化

//實際上是對使用該裝置的當前程序建立乙個節點,並把這個節點掛接到該裝置的非同步通知佇列上

//裝置狀態資訊改變時,裝置驅動通過 kill_fasync 告知非同步通知佇列中的程序

//本質是遍歷 fasync_struct 佇列,呼叫send_sigio給每個程序傳送非同步i/o通知訊息和sigio訊號

void kill_fasync(struct fasync_struct **fp, int sig, int band)

}/*輪詢*/(站在裝置的角度)

輪詢的目的:應用程式通過輪詢裝置,根據裝置返回的資訊判斷是否可以對該裝置進行[無阻塞]的訪問

輪詢的實現:通過等待佇列機制來實現,在裝置驅動程式中定義了乙個程序輪詢等待佇列

wait_queue_head_t poll_wq_write;//僅乙個頭部,該佇列的每個元素代表輪詢裝置的程序

輪詢的實質:應用程式呼叫poll函式輪詢乙個裝置檔案描述符,實質上會呼叫裝置驅動的poll函式

然後 1.將該程序新增到裝置的程序輪詢等待佇列中,通過 poll_wait 實現         

2.根據當前裝置的狀態,返回相應的狀態資訊

Linux的一些筆記

三大作業系統 unix iosmac os windows linux 安卓 android ubuntu redhat 計算機的組成 硬體 處理器 cpu 重要指標 頻率 3.3ghz i3 i5 i7 intel出品 執行記憶體ram 儲存資料 容量 位元組為單位 主機板 匯流排裝置 輸入輸出裝...

學習中的一些筆記

取得某字元最後出現處起的字串。語法 string strrchr string haystack,string needle 返回值 整數 函式種類 資料處理 內容說明 本函式用來尋找字串 haystack 中的字元 needle 最後出現位置,並將此位置起至字串 haystack 結束之間的字串返...

我的一些學習筆記

集合類和陣列之間的橋梁是由 集合類中的 toarray 方法 和 陣列類中的arrarys.aslist來充當。關於迭代器 如果要呼叫 它的remove 方法則至少要先呼叫一下 next 方法。可以認為迭代器是指向兩個元素之間的位置 呼叫一次 next 它就把前乙個元素返回 remove 方法實際上...