linux subsys_initcall

宏定義__define_initcall(level,fn)對于內核的初始化很重要,他指示編譯器在編譯的時候,將一系列初始化函數的起始地址值按照一定的順序放在一個section中。在內核初始化段,do_initcalls() 將按順序從該section中以函數指針的形式取出這些函數的起始地址,來依次完成相應的初始化。于內核某些部分的初始化需要依賴于其他某些部分的初始化的完成,因此這個順序排列常常很重要。 

  下面將從__define_initcall(level,fn) 宏定義的代碼分析入手,依次分析名稱為initcall.init的section的結構,最后分析內核初始化函數do_initcalls()是怎樣利用宏定義__define_initcall(level,fn)及其相關的衍生的7個宏宏定義,來實現內核某些部分的順序初始化的。

1、分析 __define_initcall(level,fn) 宏定義
1) 這個宏的定義位于inlclude\linux\init.h中:
#define __define_initcall(level,fn)? ?\
static initcall_t __initcall_##fn??\
__attribute__((__section__(".initcall" level ".init"))) \
= fn
其中 initcall_t 是個函數指針類型:
typedef int (*initcall_t)(void);
而屬性 __attribute__((__section__())) 則表示把對象放在一個這個由括號中的名稱所指代的section中。所以這個宏定義的的含義是:1) 聲明一個名稱為__initcall_##fn的函數指針(其中##表示替換連接,);2) 將這個函數指針初始化為fn;3) 編譯的時候需要把這個函數指針變量放置到名稱為 ".initcall" level ".init"的section中(比如level="1",代表這個section的名稱是 ".initcall1.init")。
2) 舉例:__define_initcall(6, pci_init)
上述宏調用的含義是:1) 聲明一個函數指針__initcall_pic_init = pci_init;且 2) 這個指針變量__initcall_pic_init 需要放置到名稱為 .initcall6.init的section中( 其實質就是將 這個函數pic_init的首地址放置到了這個section中)。
3) 這個宏一般并不直接使用,而是被定義成下述其他更簡單的7個衍生宏
這些衍生宏宏的定義也位于 inlclude\linux\Init.h 中:
#define core_initcall(fn)? ?? ?? ?__define_initcall("1",fn)
#define postcore_initcall(fn)? ???__define_initcall("2",fn)
#define arch_initcall(fn)? ?? ?? ?__define_initcall("3",fn)
#define subsys_initcall(fn)? ?? ? __define_initcall("4",fn)
#define fs_initcall(fn)? ?? ?? ???__define_initcall("5",fn)
#define device_initcall(fn)? ?? ? __define_initcall("6",fn)
#define late_initcall(fn)? ?? ?? ?__define_initcall("7",fn)
因此通過宏 core_initcall() 來聲明的函數指針,將放置到名稱為.initcall1.init的section中,而通過宏 postcore_initcall() 來聲明的函數指針,將放置到名稱為.initcall2.init的section中,依次類推。
4) 舉例:device_initcall(pci_init)
解釋同上 1-2)。
2、和初始化調用有關section--initcall.init被分成了7個子section
1) 他們依次是.initcall1.init、.initcall2.init、...、.initcall7.init
2) 按照先后順序依次排列
3) 他們的定義在文檔vmlinux.lds.S中
例如 對于i386+,在i386\kernel\vmlinux.lds.S中有:
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
}
__initcall_end = .;
而在makefile 中有

LDFLAGS_vmlinux += -T arch/$(ARCH)/kernel/vmlinux.lds.s
4) 在這7個section總的開始位置被標識為__initcall_start,而在結尾被標識為__initcall_end。
3、 內核初始化函數do_basic_setup(): do_initcalls() 將從.initcall.init中,也就是這7個section中依次取出任何的函數指針,并調用這些函數指針所指向的函數,來完成內核的一些相關的初始化。
這個函數的定義位于init\main.c中:
extern initcall_t __initcall_start, __initcall_end;
static void __init do_initcalls(void)
{
initcall_t *call;
....
for (call = &__initcall_start; call??

***********************************************************************

假如您希望某個初始化函數在內核初始化階段就被調用,那么您就應該使用宏__define_initcall(level,fn) 或 其7個衍生宏來把這個初始化函數fn的起始地址按照初始化的順序放置到相關的section 中。 內核初始化時的do_initcalls()將從這個section中按順序找到這些函數來執行。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254042.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254042.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254042.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue transition

Vue.js 教程 (9) : 過渡動畫 Vue.js 提供非常簡單的過渡動畫接口。這些過渡動畫在 Vue.js 將目標元素插入或移除出 DOM 的時候會自動執行。能夠觸發動畫的指令包括 v-if , v-show 和 v-repeat。同時,vm 實例的 $appendTo() , $before() , $after() 和 $remove() 方法…

VS擴展工具

原文發布時間為:2011-03-09 —— 來源于本人的百度文章 [由搬家工具導入]http://visualstudiogallery.msdn.microsoft.com/site/search?f%5B0%5D.TypeRootCategory&f%5B0%5D.Valuetools轉載于:https://www.cnblogs.com/handboy/p/7163982.html

工業相機5A參數及其對圖像采集的影響

有些相機會提到5A功能,指的是: Automatic Shutter(自動快門)、Automatic Gain(自動增益)、Automatic IRIS(自動光圈)、Automatic Gamma(自動伽馬)、Automatic White Balance(自動白平…

DM6446 OSD

DM6446 OSD TMS320DM6446支持背景窗顏色,兩個視頻窗口,兩個OSD窗口,一個指針(cursor)窗口。它們以遞增的順序排列:一個特有的第二個OSD窗口(OSDWIN1)可以用來配置成屬性窗口來控制視頻窗口和第一個OSD窗口&…

DOS的一些常用命令

原文發布時間為:2011-02-12 —— 來源于本人的百度文章 [由搬家工具導入]DOS遠程桌面連接命令 mstsc /v: 192.168.1.250 /consolecmd 運行 command刪除文件 rd 文件名/S創建文件 MD 文件名 1. net user admin godmour /add 新建一個…

機器視覺工業鏡頭-Computar

日本Computar鏡頭,全球工業鏡頭、CCTV鏡頭市場占有率第一。CBC板式會社成立于1925年,總部在日本東京。1960年 CBC香港公司成立,是computar鏡頭走向國際市場的前奏。 1979年 研制出第一只手動變焦鏡頭。 1985年 研制出第一款非球面高速鏡頭。1…

C++編程經驗總結1

面向對象的精髓: 主函數其實就是對于類的元素和動作的重新組合來進行一項活動。 一個思想概念:程設是清楚的,完美的。 數學是清楚的,是完美的。 物理是有趣的,尤其是量子物理 生物是清楚的,尤其是基因 外語…

DM365的BSP源碼分析-基于2.6.18內核

DM365的BSP主要包含mach-davinci和plat-davinci兩個目錄(及相關頭文件),BSP復雜龐大又極其重要,它主要完成了板級的初始化,比如內存映射,時鐘和電源初始化,中斷和IO初始化,CPU及各模…

第四章:Django 模型 —— 設計系統表

1. Django框架提供了完善的模型(Model )層來創建和存儲數據,每一個模型對應數據庫中的唯一的一張表。 2. Django 模型基礎知識: 。每一本模型是一個Python類,繼承了django.db.models.Model類 。該模型中每一個屬性一個…

DM365 使用BT656協議驅動LCD的實現

前兩天已經調好了,主要是對davinci_platform.c的修改 因為輸入輸出都為pal的制式,所以就在pal的函數中進行了修改。 在PAL設置的函數中,修改如下: /* * setting PAL mode */ static void davinci_enc_set_pal(struct vid_enc_mode…

工業視覺鏡頭NAVITAR

品牌介紹 美國NAVITAR是優越的上等光學系統制造商和供應商,工業視覺鏡頭NAVITAR為機器視覺、檢測和生物醫學診斷行業提供的定制光學解決方案。 工業視覺鏡頭NAVITAR用于鑒定產品、檢查產品缺陷、測量零件尺寸、操縱機器人設備和協助進行科學分析與探索。 還用來引導…

TCP系列48—擁塞控制—11、FRTO擁塞撤銷

一、概述FRTO虛假超時重傳檢測我們之前重傳章節的文章已經介紹過了,這里不再重復介紹,針對后面的示例在說明兩點1、FRTO只能用于虛假超時重傳的探測,不能用于虛假快速重傳的探測。2、延遲ER重傳觸發的進入Recovery狀態時候,并不會…

娛樂一下

6年前,沒幾個人知道尤里米爾納(Yuri Milner)是誰。但今天,他已經是地球上最有名的投資人了。 短短幾年內,這家伙掌管的風險投資基金DST(數字天空科技)投遍了全球的互聯網明星企業,并…

機器視覺行業市場現狀及發展前景分析

1.中國的機器視覺起步較晚,目前正處于快速增長期。 我國機器視覺最早起源于20世紀80年代。機器視覺生產線和先進設備自1998年眾多電子、半導體企業落戶廣東、上海以來,先后在國內誕生了國際代理商和機器視覺系統集成商。 第一個階段是1999-2003年的啟蒙…

從bootm 命令講起/U-boot的環境變量: bootcmd 和bootargs

從bootm 命令講起 1 找到linux的內核入口 Bootm命令通過讀取uImage的頭部040字節的信息,將uImage定位到正確的地址,同時找到linux的內核入口地址。 這個地方就涉及到uImage的頭部040字節信息到底是什么的問題?uboot提供了mkimage命令去把040字節加在lin…

關于創建SWAP示例

cd /data 進入指定目錄dd if/dev/zero of/data/swapfile bs1M count102400【參數說明】if文件名&#xff1a;輸入文件名&#xff0c;缺省為標準輸入。即指定源文件。< ifinput file >of文件名&#xff1a;輸出文件名&#xff0c;缺省為標準輸出。即指定目的文件。< of…

一個公式來說明加接圈的作用和缺點

一個公式來說明加接圈的作用和缺點 在很多視覺項目中&#xff0c;如果想要將視野縮小&#xff0c;一種方式是換用長焦鏡頭&#xff1b;另一種方式則是通過加接圈的方式來實現。那么&#xff0c;接圈到底改變的是什么參數&#xff0c;能夠使圖像進行放大呢&#xff1f;核心公式上…

bzoj4636: 蒟蒻的數列

作為惟一一個離線動態開點線段樹的。。我是不是沒救了。。 維護一下區間修改和區間和。。。 然而由于一些奇怪的原因翻車 到最后索性跑到一個點直接開左右兒子 最后注意區間左右端點可以相等。。。 1 #include<cstdio>2 #include<iostream>3 #include<algorithm…

module_param 在內核編程中的作用

module_param 在用戶態下編程可以通過main()的來傳遞命令行參數&#xff0c;而編寫一個內核模塊則通過module_param()! module_param的作用一.module_param1.為什么引入 在用戶態下編程可以通過main()來傳遞命令行參數&#xff0c;而編寫一個內核模塊則可通過module_param()來傳…