上一篇博文的地址:
http://blog.csdn.NET/morixinguan/article/details/65494239
這節(jié),我們來看看函數指針與回調函數在Linux內核中的應用。
從上節(jié)我們了解到,函數指針和回調函數在開發(fā)者和用戶之間的一個例子,那么這節(jié),我將引用Linux內核中文件操作結構體來詳細的說明。
我們首先來看到這個結構體,這段代碼位于linux內核的include/linux/fs.h中,由于代碼眾多,我只截取幾個最基本的例子:
File_operations文件操作結構體:
這段代碼中,利用結構體的封裝思想,將函數指針封裝在一個file_operations結構體里,然后,在具體實現驅動的時候,實現具體的函數,再賦值給結構體里的函數指針做好初始化操作,我們來看看友善之臂的led驅動就明白了。
以下這段代碼截取友善之臂提供的linux內核中的tiny4412_leds.c
首先,先是定義了一個結構體變量,并對結構體變量進行初始化,在這個驅動中,只實現了ioctl函數,對照著上面的結構體,ulocked_ioctl就是結構體中的這個函數指針。
long (*unlocked_ioctl) (struct file *,unsigned int, unsigned long);
再來看看友善實現的adc驅動里,也是這么來做,這里看到 : 也是C語言結構體的一種初始化方式,也是合理的。
在內核中,有很多這樣的函數指針,所以,當我們了解了這樣的套路以后,再去學習linux內核,我們的思想就會清晰很多了。
再來看看回調函數在linux內核里的基本應用。
從上節(jié)我們了解到,回調函數的本質其實也就是函數指針,只不過定義有所區(qū)別。它的定義就是:你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。
接下來我們來看一個例子:
這段代碼摘自友善之臂的button驅動:
我們在tiny4412_buttons_open函數里看到
err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH,
buttons[i].name,(void *)&buttons[i]);
我們來看看request_irq這個函數:
這個函數的作用是請求中斷,我們來看看函數的第二個參數irq_handler_t handler是什么?
到這里我們就明白了,第二個參數是一個用typedef重新定義的一個新類型的函數指針。
那么也就是說一旦執(zhí)行了tiny4412的open函數,就會通過request_irq去通過回調函數去執(zhí)行按鍵中斷,并返回一個中斷句柄。這個回調函數,其實就是一個中斷服務函數。
回調函數在內核中就是這么來使用的,當然,還有其它的,比如我們在tiny4412的open函數里面還看到:
setup_timer(&buttons[i].timer,tiny4412_buttons_timer,
(unsignedlong)&buttons[i]);
這個函數的作用是注冊一個定時器,通過回調函數tiny4412_buttons_timer來進行觸發(fā)。
如果你不看它的定義,你可能以為它是一個普通函數,其實它是一個宏函數。
這個宏函數通過調用setup_timer_key這個函數來實現定時器的注冊:
通過這一節(jié),我們了解到回調函數在Linux內核中的應用,為學習Linux內核,分析linux內核源代碼打下了基礎。
免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯系我們,謝謝!





