欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言 module_init函數(shù)與initcall案例詳解

 更新時(shí)間:2021年08月25日 09:13:37   作者:penghan  
這篇文章主要介紹了C語(yǔ)言 module_init函數(shù)與initcall案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下

module_init這個(gè)函數(shù)對(duì)做驅(qū)動(dòng)的人來(lái)說(shuō)肯定很熟悉,這篇文章用來(lái)跟一下這個(gè)函數(shù)的實(shí)現(xiàn)。

在include/linux/init.h里面有module_init的定義,自然,因?yàn)橐粋€(gè)module可以在內(nèi)核啟動(dòng)時(shí)自動(dòng)加載進(jìn)內(nèi)核,也可以由我們手動(dòng)在需要時(shí)加載進(jìn)內(nèi)核,基于這種場(chǎng)景,內(nèi)核使用了MODULE這個(gè)宏,見代碼:

#ifndef MODULE

#ifndef __ASSEMBLY__

...

#define __define_initcall(level,fn,id) \
    static initcall_t __initcall_##fn##id __attribute_used__ \
    __attribute__((__section__(".initcall" level ".init"))) = fn

#define pure_initcall(fn)        __define_initcall("0",fn,0)

#define core_initcall(fn)        __define_initcall("1",fn,1)
#define core_initcall_sync(fn)        __define_initcall("1s",fn,1s)
#define postcore_initcall(fn)        __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn)    __define_initcall("2s",fn,2s)
#define arch_initcall(fn)        __define_initcall("3",fn,3)
#define arch_initcall_sync(fn)        __define_initcall("3s",fn,3s)
#define subsys_initcall(fn)        __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)
#define fs_initcall(fn)            __define_initcall("5",fn,5)
#define fs_initcall_sync(fn)        __define_initcall("5s",fn,5s)
#define rootfs_initcall(fn)        __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn)        __define_initcall("6",fn,6)
#define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
#define late_initcall(fn)        __define_initcall("7",fn,7)
#define late_initcall_sync(fn)        __define_initcall("7s",fn,7s)

#define __initcall(fn) device_initcall(fn)

#define module_init(x)    __initcall(x);

#else /* MODULE */

...

#define module_init(initfn)                    \
    static inline initcall_t __inittest(void)        \
    { return initfn; }                    \
    int init_module(void) __attribute__((alias(#initfn)));...

當(dāng)我們使用make menuconfig來(lái)配置內(nèi)核時(shí),將某個(gè)module配置為m時(shí),MODULE這個(gè)宏就被定義了,而當(dāng)配置為y時(shí),則沒有定義,具體的實(shí)現(xiàn)在kernel的根Makefile(-DMODULE)里。

現(xiàn)在我們先看下第一種情況,即把module配置為m的情況,即else分支的代碼。

先看下initcall_t的定義:

typedef int (*initcall_t)(void);

它是一個(gè)接收參數(shù)為void, 返回值為int類型的函數(shù)指針。這樣就明白了,其實(shí)前兩句話只是做了一個(gè)檢測(cè),當(dāng)你傳進(jìn)來(lái)的函數(shù)指針的參數(shù)和返回值與initcall_t不一致時(shí),就會(huì)有告警。
重點(diǎn)在第三句,是使用alias將initfn變名為init_module,我們知道,kernel 2.4版本之前都是用init_module來(lái)加載模塊的。這樣做應(yīng)該是為了不用修改load module的那塊代碼吧。

當(dāng)我們調(diào)用insmod將module加載進(jìn)內(nèi)核時(shí),會(huì)去找init_module作為入口地址,即是我們的initfn, 這樣module就被加載了。

取nvme.ko為例,我們可以通過(guò)objdump -t nvme.ko 查看該模塊的符號(hào)表,發(fā)現(xiàn)init_module和nvme_init指向同一個(gè)偏移量。如下:

現(xiàn)在看第二種情況,即我們選擇將模塊編進(jìn)內(nèi)核,讓它隨內(nèi)核啟動(dòng)而加載。

這種情況下module_init最終會(huì)調(diào)用__define_initcall宏,這個(gè)宏的作用就是將我們的初始化函數(shù)放在".initcall" level ".init"中。

在這里是.initcall6.init, 它的位置可以在Vmlinux.lds.h里面找到:

#define INITCALLS                            \
      *(.initcall0.init)                        \
      *(.initcall0s.init)                        \
      *(.initcall1.init)                        \
      *(.initcall1s.init)                        \
      *(.initcall2.init)                        \
      *(.initcall2s.init)                        \
      *(.initcall3.init)                        \
      *(.initcall3s.init)                        \
      *(.initcall4.init)                        \
      *(.initcall4s.init)                        \
      *(.initcall5.init)                        \
      *(.initcall5s.init)                        \
    *(.initcallrootfs.init)                        \
      *(.initcall6.init)                        \
      *(.initcall6s.init)                        \
      *(.initcall7.init)                        \
      *(.initcall7s.init)

而INITCALL可以在vmlinux.lds.S里面找到:

.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
      __init_begin = .;
    _sinittext = .;
    *(.init.text)
    _einittext = .;
  }
  .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
  . = ALIGN(16);
  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
      __setup_start = .;
    *(.init.setup)
      __setup_end = .;
   }
  .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
      __initcall_start = .;
    INITCALLS
      __initcall_end = .;
  }
  .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
      __con_initcall_start = .;
    *(.con_initcall.init)
      __con_initcall_end = .;
  }

上面貼出來(lái)的代碼是系統(tǒng)啟動(dòng)時(shí)存放初始化數(shù)據(jù)的地方,執(zhí)行完成后不再需要,會(huì)被釋放掉。根據(jù)上面的內(nèi)存布局,可以列出初始化宏和內(nèi)存的對(duì)應(yīng)關(guān)系:

_init_begin              -------------------

                        |  .init.text       | ---- __init

                        |-------------------|

                        |  .init.data       | ---- __initdata

_setup_start       |-------------------|

                        |  .init.setup      | ---- __setup_param

__initcall_start   |-------------------|

                        |  .initcall1.init  | ---- core_initcall

                        |-------------------|

                        |  .initcall2.init  | ---- postcore_initcall

                        |-------------------|

                        |  .initcall3.init  | ---- arch_initcall

                        |-------------------|

                        |  .initcall4.init  | ---- subsys_initcall

                        |-------------------|

                        |  .initcall5.init  | ---- fs_initcall

                        |-------------------|

                        |  .initcall6.init  | ---- device_initcall

                        |-------------------|

                        |  .initcall7.init  | ---- late_initcall

__initcall_end    |-------------------|

                        |                   |

                        |    ... ... ...    |

                        |                   |

__init_end              -------------------

而各個(gè)initcall被調(diào)用的地方在kernel_init-》do_basic_setup-》do_initcalls里面:

static void __init do_initcalls(void)
{
    initcall_t *call;
    int count = preempt_count();

    for (call = __initcall_start; call < __initcall_end; call++) {
        ktime_t t0, t1, delta;
        char *msg = NULL;
        char msgbuf[40];
        int result;

        if (initcall_debug) {
            printk("Calling initcall 0x%p", *call);
            print_fn_descriptor_symbol(": %s()",
                    (unsigned long) *call);
            printk("\n");
            t0 = ktime_get();
        }

        result = (*call)();
...
}

到此這篇關(guān)于C語(yǔ)言 module_init函數(shù)與initcall案例詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言 module_init函數(shù)與initcall內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入了解C++ 結(jié)構(gòu)體(struct)與共用體(union)

    深入了解C++ 結(jié)構(gòu)體(struct)與共用體(union)

    這篇文章主要介紹了C++ 結(jié)構(gòu)體與共用體的的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-08-08
  • C語(yǔ)言中循環(huán)嵌套的應(yīng)用方式

    C語(yǔ)言中循環(huán)嵌套的應(yīng)用方式

    這篇文章主要介紹了C語(yǔ)言中循環(huán)嵌套的應(yīng)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C語(yǔ)言判斷數(shù)是否為素?cái)?shù)與素?cái)?shù)輸出

    C語(yǔ)言判斷數(shù)是否為素?cái)?shù)與素?cái)?shù)輸出

    大家好,本篇文章主要講的是C語(yǔ)言判斷數(shù)是否為素?cái)?shù)與素?cái)?shù)輸出,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • C語(yǔ)言 二級(jí)指針詳解及示例代碼

    C語(yǔ)言 二級(jí)指針詳解及示例代碼

    本文主要介紹C語(yǔ)言 二級(jí)指針,這里整理了C語(yǔ)言中二級(jí)指針的基礎(chǔ)資料并附有示例代碼和實(shí)現(xiàn)結(jié)果,幫助大家學(xué)習(xí)理解相關(guān)知識(shí),有學(xué)習(xí)的朋友可以參考下
    2016-08-08
  • C語(yǔ)言編程數(shù)據(jù)結(jié)構(gòu)帶頭雙向循環(huán)鏈表全面詳解

    C語(yǔ)言編程數(shù)據(jù)結(jié)構(gòu)帶頭雙向循環(huán)鏈表全面詳解

    這篇文章主要為大家介紹了C語(yǔ)言編程的數(shù)據(jù)結(jié)構(gòu)中帶頭雙向循環(huán)鏈表全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助祝大家多多進(jìn)步,早日升職加薪
    2021-10-10
  • C++生成不重復(fù)的隨機(jī)整數(shù)

    C++生成不重復(fù)的隨機(jī)整數(shù)

    這篇文章主要為大家詳細(xì)介紹了C++生成不重復(fù)的隨機(jī)整數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • C++算法與泛型算法(algorithm、numeric)

    C++算法與泛型算法(algorithm、numeric)

    這篇文章主要介紹了C++算法與泛型算法(algorithm、numeric),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • C語(yǔ)言實(shí)現(xiàn)俄羅斯方塊課程設(shè)計(jì)

    C語(yǔ)言實(shí)現(xiàn)俄羅斯方塊課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)俄羅斯方塊課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++ 智能指針的魅力你都了解嗎

    C++ 智能指針的魅力你都了解嗎

    智能指針使用和普通指針類似。解引用一個(gè)智能指針返回它指向的對(duì)象。如果在一個(gè)條件判斷中使用智能指針,效果就是檢測(cè)它是否為空,本文給大家介紹C++ 智能指針的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-06-06
  • C++?OpenCV中幾種基本的圖像處理方式

    C++?OpenCV中幾種基本的圖像處理方式

    大家好,本篇文章主要講的是C++?OpenCV中幾種基本的圖像處理方式,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01

最新評(píng)論