天天看點

深入淺出剖析C語言函數指針與回調函數(二)

上一篇博文的位址:

http://blog.csdn.net/morixinguan/article/details/65494239

這節,我們來看看函數指針與回調函數在Linux核心中的應用。

從上節我們了解到,函數指針和回調函數在開發者和使用者之間的一個例子,那麼這節,我将引用Linux核心中檔案操作結構體來詳細的說明。

我們首先來看到這個結構體,這段代碼位于linux核心的include/linux/fs.h中,由于代碼衆多,我隻截取幾個最基本的例子:

File_operations檔案操作結構體:

深入淺出剖析C語言函數指針與回調函數(二)

這段代碼中,利用結構體的封裝思想,将函數指針封裝在一個file_operations結構體裡,然後,在具體實作驅動的時候,實作具體的函數,再指派給結構體裡的函數指針做好初始化操作,我們來看看友善之臂的led驅動就明白了。

以下這段代碼截取友善之臂提供的linux核心中的tiny4412_leds.c

深入淺出剖析C語言函數指針與回調函數(二)

首先,先是定義了一個結構體變量,并對結構體變量進行初始化,在這個驅動中,隻實作了ioctl函數,對照着上面的結構體,ulocked_ioctl就是結構體中的這個函數指針。

long (*unlocked_ioctl) (struct file *,unsigned int, unsigned long);

再來看看友善實作的adc驅動裡,也是這麼來做,這裡看到 : 也是C語言結構體的一種初始化方式,也是合理的。

深入淺出剖析C語言函數指針與回調函數(二)

      在核心中,有很多這樣的函數指針,是以,當我們了解了這樣的套路以後,再去學習linux核心,我們的思想就會清晰很多了。

       再來看看回調函數在linux核心裡的基本應用。

接下來我們來看一個例子:

這段代碼摘自友善之臂的button驅動:

深入淺出剖析C語言函數指針與回調函數(二)

我們在tiny4412_buttons_open函數裡看到

err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH,

                                 buttons[i].name,(void *)&buttons[i]);

我們來看看request_irq這個函數:

深入淺出剖析C語言函數指針與回調函數(二)

這個函數的作用是請求中斷,我們來看看函數的第二個參數irq_handler_t handler是什麼?

深入淺出剖析C語言函數指針與回調函數(二)

到這裡我們就明白了,第二個參數是一個用typedef重新定義的一個新類型的函數指針。

那麼也就是說一旦執行了tiny4412的open函數,就會通過request_irq去通過回調函數去執行按鍵中斷,并傳回一個中斷句柄。這個回調函數,其實就是一個中斷服務函數。

深入淺出剖析C語言函數指針與回調函數(二)

   回調函數在核心中就是這麼來使用的,當然,還有其它的,比如我們在tiny4412的open函數裡面還看到:

   setup_timer(&buttons[i].timer,tiny4412_buttons_timer,

              (unsignedlong)&buttons[i]);

   這個函數的作用是注冊一個定時器,通過回調函數tiny4412_buttons_timer來進行觸發。

如果你不看它的定義,你可能以為它是一個普通函數,其實它是一個宏函數。

深入淺出剖析C語言函數指針與回調函數(二)

   這個宏函數通過調用setup_timer_key這個函數來實作定時器的注冊:

深入淺出剖析C語言函數指針與回調函數(二)

通過這一節,我們了解到回調函數在Linux核心中的應用,為學習Linux核心,分析linux核心源代碼打下了基礎。

繼續閱讀