中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

中小企業(yè)的網(wǎng)站建設(shè)seo怎么學(xué)

中小企業(yè)的網(wǎng)站建設(shè),seo怎么學(xué),wordpress 后臺(tái)演示,創(chuàng)辦個(gè)人網(wǎng)站如何管理驅(qū)動(dòng)模塊 由于Linux驅(qū)動(dòng)模塊眾多,系統(tǒng)對(duì)模塊加載順序有要求,一些基礎(chǔ)模塊在系統(tǒng)啟動(dòng)時(shí)需要很早就被加載;開(kāi)發(fā)者加入自己的模塊時(shí),需要維護(hù)一個(gè)模塊初始化列表,上面兩方面的做起來(lái)很困難,為了科學(xué)地…

如何管理驅(qū)動(dòng)模塊

由于Linux驅(qū)動(dòng)模塊眾多,系統(tǒng)對(duì)模塊加載順序有要求,一些基礎(chǔ)模塊在系統(tǒng)啟動(dòng)時(shí)需要很早就被加載;開(kāi)發(fā)者加入自己的模塊時(shí),需要維護(hù)一個(gè)模塊初始化列表,上面兩方面的做起來(lái)很困難,為了科學(xué)地管理這些模塊,首先要解決兩個(gè)問(wèn)題:

  1. 如何方便開(kāi)發(fā)者快捷加入自己的模塊
  2. 如何管理模塊的加載順序

Linux 內(nèi)核開(kāi)發(fā)者是怎么實(shí)現(xiàn)的呢?在內(nèi)核鏡像文件中,自定義了一個(gè)段,這個(gè)段里面專(zhuān)門(mén)用來(lái)存放這些初始化函數(shù)的地址,內(nèi)核啟動(dòng)時(shí),只需要在這個(gè)段地址處取出函數(shù)指針,依次執(zhí)行即可。

對(duì)模塊的開(kāi)發(fā)者,Linux內(nèi)核提供了統(tǒng)一的宏定義接口,驅(qū)動(dòng)開(kāi)發(fā)者只需要將驅(qū)動(dòng)程序用這些宏定義來(lái)修飾,這個(gè)模塊的初始化函數(shù)接口的指針就被自動(dòng)添加到了上述的段中,開(kāi)發(fā)者完全不需要關(guān)心這個(gè)實(shí)現(xiàn)的細(xì)節(jié)。

對(duì)于各種各樣的驅(qū)動(dòng)而言,會(huì)存在一定的依賴(lài)關(guān)系,需要遵循先后順序來(lái)進(jìn)行初始化,考慮到這個(gè)問(wèn)題,Linux內(nèi)核開(kāi)發(fā)者也對(duì)這一部分的初始化順序做了分級(jí)處理。


Linux驅(qū)動(dòng)模塊的加載方式

Linux 驅(qū)動(dòng)模塊有兩種加載方式,一是靜態(tài)編譯鏈接進(jìn)內(nèi)核,在系統(tǒng)啟動(dòng)過(guò)程中進(jìn)行初始化;另外一是編譯成可動(dòng)態(tài)加載的module,通過(guò)insmod動(dòng)態(tài)加載重定位到內(nèi)核。


Linux 使用宏定義

Linux提供了一組宏定義對(duì)模塊進(jìn)行靜態(tài)和動(dòng)態(tài)加載,同時(shí)對(duì)不同的模塊加載順序做了處理,提供了不同的宏定義方法。這組宏定義在路徑/kernel/include/linux/init.h中。

#ifndef MODULE#define __define_initcall(level,fn,id) \static initcall_t __initcall_##fn##id __used \__attribute__((__section__(".initcall" level ".init"))) = fn#define early_initcall(fn)	    	__define_initcall("early",fn,early)
#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 *//* Don't use these in modules, but some people do... */
#define early_initcall(fn)		module_init(fn)
#define core_initcall(fn)		module_init(fn)
#define postcore_initcall(fn)	module_init(fn)
#define arch_initcall(fn)		module_init(fn)
#define subsys_initcall(fn)		module_init(fn)
#define fs_initcall(fn)			module_init(fn)
#define device_initcall(fn)		module_init(fn)
#define late_initcall(fn)		module_init(fn)
#define security_initcall(fn)	module_init(fn)/* Each module must use one module_init(). */
#define module_init(initfn)					\static inline initcall_t __inittest(void)		\{ return initfn; }					\int init_module(void) __attribute__((alias(#initfn)));/* This is only required if you want to be unloadable. */
#define module_exit(exitfn)					\static inline exitcall_t __exittest(void)		\{ return exitfn; }					\void cleanup_module(void) __attribute__((alias(#exitfn)));
#endif /*end ifndef MODULE*/

Makefile是如何控制模塊的加載模式的?在init.h中可以看到下面的宏定義:

#ifndef MODULE
// 宏定義--->(靜態(tài)加載方式)
#else 
// 宏定義--->(動(dòng)態(tài)加載方式)
#endif

當(dāng)配置Makefiel時(shí),將某個(gè)module配置為obj-m時(shí),MODULE 這個(gè)宏就被定義,此時(shí)當(dāng)前模塊就被編譯到內(nèi)核代碼中,內(nèi)核啟動(dòng)時(shí)這個(gè)模塊就被靜態(tài)加載,反之,模塊配置為obj-y,當(dāng)前模塊被配置為動(dòng)態(tài)加載方式。


宏定義 __define_initcall 分析

我們看看如何解析這個(gè)宏__define_initcall:

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

_ * attribute * _ () 是gnu C中的擴(kuò)展語(yǔ)法,它可以用來(lái)實(shí)現(xiàn)很多靈活的定義行為。
_ * attribute * _ ((_ * section * _ (“.initcall” #id “.init”)))表示編譯時(shí)將目標(biāo)符號(hào)放置在括號(hào)指定的段中。

在宏定義中,# 的作用是將目標(biāo)字符串化,## 在宏定義中的作用是符號(hào)連接,將多個(gè)符號(hào)連接成一個(gè)符號(hào),并不字符串化。

level是一個(gè)數(shù)字或者是數(shù)字+s,這個(gè)數(shù)字代表這個(gè)fn執(zhí)行的優(yōu)先級(jí),數(shù)字越小,優(yōu)先級(jí)越高,帶s的fn優(yōu)先級(jí)低于不帶s的fn優(yōu)先級(jí)

__used是一個(gè)宏定義

#define __used __attribute__((__used__))

使用前提是在編譯器編譯過(guò)程中,如果定義的符號(hào)沒(méi)有被引用,編譯器就會(huì)對(duì)其進(jìn)行優(yōu)化,不保留這個(gè)符號(hào),而__attribute__((used))的作用是告訴編譯器這個(gè)靜態(tài)符號(hào)在編譯的時(shí)候即使沒(méi)有使用到也要保留這個(gè)符號(hào)。

這里的 initcall_t 是函數(shù)指針類(lèi)型,對(duì)應(yīng)的段:.initcall,如下:

typedef int (*initcall_t)(void);

上面所述,這個(gè)宏將我們的初始化函數(shù)放在".initcall" level ".init"中。這個(gè)段可以在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 = .;}

Vmlinux.lds.h 中是系統(tǒng)啟動(dòng)時(shí)存放初始化數(shù)據(jù)的指針,執(zhí)行完成后會(huì)被釋放掉內(nèi)存。根據(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         |-------------------|

宏定義 #define module_init(initfn)

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

前兩句話只是做了一個(gè)檢測(cè),當(dāng)傳進(jìn)來(lái)的函數(shù)指針的參數(shù)和返回值與initcall_t不一致時(shí),就會(huì)有告警。第三句,是使用alias將initfn變名為init_module,當(dāng)調(diào)用insmod將module加載進(jìn)內(nèi)核時(shí),就會(huì)去找init_module作為入口地址,即傳進(jìn)來(lái)的initfn, 這樣module就被加載了。


舉例:

為了更方便地理解,我們舉個(gè)例子來(lái)說(shuō)明,開(kāi)發(fā)者聲明了這樣一個(gè)函數(shù):module_init(hello_init);

首先宏展開(kāi)成:__define_initcall(“6”,hello_init, 6)
然后接著展開(kāi):static initcall_t __initcall_hello_init6 = hello_init; 定義了函數(shù)指針變量。
同時(shí)聲明 __initcall_hello_init6 這個(gè)變量即使沒(méi)被引用也保留符號(hào),且將其放置在內(nèi)核鏡像的.initcall6.init段處。


xxx_initcall()宏定義調(diào)用追蹤


從上面的分析,我們知道xxx_initcall是如何被定義,知道目標(biāo)函數(shù)的放置位置,那么使用xxx_initcall()修飾的函數(shù)是怎么被調(diào)用的呢?下面就從內(nèi)核 init/main.c函數(shù)起始部分start_kernel開(kāi)始往下追蹤,它的調(diào)用順序?yàn)?#xff1a;

start_kernel  -> rest_init();-> kernel_thread(kernel_init, NULL, CLONE_FS);-> kernel_init()-> do_basic_setup();-> do_initcalls();

rest_init();啟動(dòng) RCU 鎖調(diào)度器 ,調(diào)用函數(shù) kernel_thread 創(chuàng)建 kernel_init 進(jìn)程,也就是 init 內(nèi)核進(jìn)程, init 進(jìn)程的 PID 為 1。調(diào)用函數(shù) kernel_thread 創(chuàng)建 kthreadd 內(nèi)核進(jìn)程,此內(nèi)核進(jìn)程的 PID 為 2。kthreadd 進(jìn)程負(fù)責(zé)所有內(nèi)核進(jìn)程的調(diào)度和管理。

do_initcalls() 在這個(gè)函數(shù)中執(zhí)行所有使用xxx_initcall()聲明的函數(shù),完成 Linux 下驅(qū)動(dòng)模型子系統(tǒng)的初始化。

static void __init do_initcalls(void)
{initcall_t *fn;for (fn = __early_initcall_end; fn < __initcall_end; fn++)do_one_initcall(*fn);
}

函數(shù)中的 fn 為函數(shù)指針,fn++ 相當(dāng)于函數(shù)指針+1,相當(dāng)于內(nèi)存地址+sizeof(fn)。

int do_one_initcall(initcall_t fn)
{ret.result = fn();//執(zhí)行功能函數(shù)
}

在do_one_initcall函數(shù)里執(zhí)行被初始化的模塊。

http://www.risenshineclean.com/news/27227.html

相關(guān)文章:

  • 企業(yè)對(duì)電子商務(wù)網(wǎng)站的建設(shè)百度官方網(wǎng)站網(wǎng)址是多少
  • 東莞大嶺山鎮(zhèn)網(wǎng)站建設(shè)新聞式軟文
  • 自己開(kāi)網(wǎng)站工作室阿里云域名查詢(xún)和注冊(cè)
  • 企業(yè)網(wǎng)站的缺點(diǎn)有域名了怎么建立網(wǎng)站
  • 大連網(wǎng)站推廣招聘手機(jī)優(yōu)化大師為什么扣錢(qián)
  • 昆山做網(wǎng)站的jofuns市場(chǎng)營(yíng)銷(xiāo)一般在哪上班
  • 純靜態(tài)網(wǎng)站部署服務(wù)器跨界營(yíng)銷(xiāo)案例
  • 優(yōu)秀網(wǎng)站設(shè)計(jì)效果圖企業(yè)營(yíng)銷(xiāo)推廣怎么做
  • 格力網(wǎng)站建設(shè)首頁(yè)友情鏈接交換的作用在于
  • 廣東網(wǎng)站建設(shè)便捷抖音seo優(yōu)化
  • 哪些網(wǎng)站可以接單做推廣搜索引擎
  • 網(wǎng)站建設(shè)客服電話怎么找百度seo刷排名工具
  • 水電維修在哪個(gè)網(wǎng)站上做推廣好些系統(tǒng)優(yōu)化軟件
  • 怎么建個(gè)自己的網(wǎng)站seo建站收費(fèi)地震
  • 網(wǎng)站建設(shè)資訊平臺(tái)關(guān)鍵詞權(quán)重查詢(xún)
  • 達(dá)州做網(wǎng)站的公司b站引流推廣
  • 網(wǎng)站后臺(tái)添加投票系統(tǒng)電子商務(wù)網(wǎng)站建設(shè)方案
  • 做網(wǎng)站不會(huì)P圖怎么辦seo詞庫(kù)排行
  • 游戲ui設(shè)計(jì)落實(shí)20條優(yōu)化措施
  • 網(wǎng)站建設(shè)硬件網(wǎng)站怎么優(yōu)化推廣
  • 江蘇城鄉(xiāng)建設(shè)職業(yè)學(xué)院就業(yè)網(wǎng)站seo賺錢(qián)項(xiàng)目
  • 網(wǎng)站怎么進(jìn)行優(yōu)化排名福建鍵seo排名
  • 仿win8網(wǎng)站百度站長(zhǎng)工具seo綜合查詢(xún)
  • 梅花網(wǎng)官網(wǎng)免費(fèi)素材中國(guó)seo排行榜
  • 企業(yè)建站有什么好處百度秒收錄軟件工具
  • 新鄉(xiāng)網(wǎng)站開(kāi)發(fā)的公司谷歌瀏覽器下載安裝
  • 網(wǎng)站建設(shè)伍際網(wǎng)絡(luò)百度搜索推廣方法
  • 最近新聞大事件摘抄游戲優(yōu)化大師有用嗎
  • 網(wǎng)站如何添加白名單百度關(guān)鍵詞收錄排名
  • 求職網(wǎng)站開(kāi)發(fā)我想注冊(cè)一個(gè)網(wǎng)站怎么注冊(cè)