如何編寫跨平臺的C語言代碼?

嵌入式大雜燴 2023-06-09 22:03

弱符號

弱符號是指在定義或者聲明一個對象(變量、結(jié)構(gòu)體成員、函數(shù))時,在對象的前面添加?__attribute__((weak))?標(biāo)志所得到的對象符號。如下所示函數(shù)即為一個弱對象符號 void test_weak_attr(void),或者稱該函數(shù)是弱函數(shù)屬性的、虛函數(shù)。

__attribute__((weak)) void test_weak_attr(void)// 或者使用如下樣式的定義,兩者等效void __attribute__((weak)) test_weak_attr(void){    printf("Weak Func!\r\n");}

弱符號的作用與示例

弱符號是相對于強(qiáng)符號而言的,在定義或者聲明變量、函數(shù)時,未添加?__attribute__((weak))?標(biāo)識的就默認(rèn)為強(qiáng)符號。如下,最普通的函數(shù)定義,就是定義了一個強(qiáng)符號 void test_strong_ref(void):

void test_weak_attr(void){    printf("this is a strong func\r\n");}


驅(qū)動程序往往需要考慮兼容性,因?yàn)橐嫒魏芏鄰S商的不同型號的設(shè)備。若驅(qū)動程序中使用強(qiáng)符號定義一些與適配的設(shè)備的特性相關(guān)的功能,則下次適配其他設(shè)備時,該強(qiáng)符號函數(shù)可能需要被修改,以兼容新的設(shè)備。當(dāng)適配的設(shè)備很多時,頻繁地更改驅(qū)動代碼將破壞驅(qū)動的可維護(hù)性。

弱符號的出現(xiàn)可以很好地解決該問題。弱符號的對象具有可以被重定義的功能(即可以被重載)。下面通過測試說明弱符號這種可被重載的特性。

在 test_weak_attr.c 程序中定義如下弱函數(shù):

// test_weak_attr.c#include  __attribute__((weak)) void test_weak_attr(void){    printf("this is a weak func\r\n");}


在 main.c 中定義如下程序:

// main.cvoid test_weak_attr(void){    printf("this is a strong func\r\n");} void app_main(void){    printf("init done\r\n");         test_weak_attr();}


編譯運(yùn)行該 main.c 程序,得到的結(jié)果是什么樣子的呢?

1

this is a strong func

將 main.c 中的 void test_weak_attr(void) 函數(shù)注釋掉,再重新編譯運(yùn)行程序得到的結(jié)果是:

1

this is a weak func

小結(jié):在使用弱符號函數(shù)時,我們可以重新定義一個同名的強(qiáng)符號函數(shù)來替代它;若沒有重新定義一個強(qiáng)函數(shù)來替換它,就使用弱函數(shù)的實(shí)現(xiàn)。弱函數(shù)就好像是一個可以被替換的“默認(rèn)函數(shù)”。

值得一提的是,舊版本的編譯器還可以使用如下方式的定義(僅聲明無效)將一個對象定義為一個弱對象:

1

2

3

4

__weak void f(void)

{

//code

}

在 linux 的一些代碼中,__weak 其實(shí)就是通過?__attribute__((weak))的重命名,兩者等效。

弱引用

弱引用是在聲明一個對象時,通過__attribute__ ((weakref())?定義一個符號的引用關(guān)系。如下所示即定義 test_weakref() 函數(shù)弱引用 test_weak_ref() 函數(shù)。

1

static void test_weakref(void) __attribute__ ((weakref("test_weak_ref")));

弱引用是相對于強(qiáng)引用而言的。未通過?__attribute__ ((weakref())?的符號和實(shí)現(xiàn)代碼之間的關(guān)系是強(qiáng)引用。如下即為一個強(qiáng)引用函數(shù)。它直接給出了 函數(shù) test_strong_ref(void)?的實(shí)現(xiàn)。

1

2

3

4

static void test_strong_ref(void)

{

????printf("this is a strong ref\r\n");

}

在編譯程序的時候,我們可以直接使用 test_strong_ref(void)?而不必?fù)?dān)心編譯不通過。如果,我沒有時間去實(shí)現(xiàn) test_strong_ref(void) ,還想在程序里先使用該函數(shù)那該如何呢?(是的,就是想白嫖,不想實(shí)現(xiàn),還想先在程序里使用這個函數(shù))。

這個時候弱引用就派上用場了。可以先將該函數(shù)定義為弱引用插入到代碼中,待后期有時間再慢慢優(yōu)化代碼實(shí)現(xiàn)這個函數(shù)完整的功能。下面結(jié)合測試進(jìn)行說明。

測試代碼1:


static void test_weakref(void) __attribute__ ((weakref("test_weak_ref")));void app_main(void){    printf("init done\r\n");    if (test_weakref) {        test_weakref();    } else {        printf("There is no weakref\r\n");    }}


測試結(jié)果:

There is no weakref

測試代碼2:

void test_weak_ref(void){    printf("this is a weak ref\n");}static void test_weakref(void) __attribute__ ((weakref("test_weak_ref")));void app_main(void){    printf("init done\r\n");    if (test_weakref) {        test_weakref();    } else {        printf("There is no weakref\r\n");    }}


測試結(jié)果:

this is a weak ref

小結(jié):強(qiáng)引用,在未定義該強(qiáng)引用的實(shí)現(xiàn)時,編譯會報(bào)錯誤:未定義的引用。弱引用允許定義一個未實(shí)現(xiàn)(未實(shí)例化)的對象,這在編譯的時候會將該對象處理成 NULL,編譯器并不會報(bào)錯。通過使用弱引用可以實(shí)現(xiàn)后期優(yōu)化代碼的功能。而避免改動使用該函數(shù)的地方。使用弱函數(shù)可以實(shí)現(xiàn)類似“鉤子(hook)"函數(shù)的功能。

實(shí)際上,包括C、python、go 編程語言在內(nèi)的很多語言 都有類似用法,本篇文章敘述的方法同樣適用于這些語言的相關(guān)開發(fā)。

注意:弱引用僅在靜態(tài)編譯中有效,動態(tài)鏈接中可能無效。

總結(jié)

弱符號、弱引用都是增強(qiáng)程序的可維護(hù)性的方法。弱符號通過可以被重定義的特性,實(shí)現(xiàn)可以被替換實(shí)現(xiàn)。弱引用通過可以暫時使用一個未定義的函數(shù)的功能,實(shí)現(xiàn)允許后期再實(shí)現(xiàn)該函數(shù)具體功能,而不必?fù)?dān)心編譯不通過。

為了方便理解,我們先預(yù)設(shè)一個應(yīng)用場景:

我們編寫了一個模擬IIC的驅(qū)動,希望它能夠在不同的的平臺運(yùn)行,目標(biāo)的平臺就設(shè)為 stm32 標(biāo)準(zhǔn)庫,stm32 HAL 庫,stm32 LL 庫,和 RT-Thread Driver 驅(qū)動庫。

或許讀者有疑惑,為什么同樣是 stm32 ,卻分成三個平臺呢?這是因?yàn)閺目缙脚_軟件編寫者的角度看,只要調(diào)用的庫的 API 不一致,就和換一個不同的平臺沒有什么本質(zhì)的差別,如果在代碼中寫死了 API 的調(diào)用,即使是同一個平臺,仍然像多平臺一樣不能運(yùn)行。

由此可以看出,跨平臺的困難所在,也不是由硬件平臺所導(dǎo)致的,而是由代碼所依賴的 API 的不同導(dǎo)致的。同一個平臺,如果依賴的 API 不同,代碼就不能跨平臺,同樣地,不同的平臺,如果依賴的 API 相同,也可以跨平臺。

所以歸根結(jié)底,是代碼所依賴的 API 出現(xiàn)了不同,所以下文中所說的“平臺”,實(shí)際上對應(yīng)的是一套 API 。

我們繼續(xù)說這個模擬 IIC 的驅(qū)動,模擬 IIC 驅(qū)動是使用 GPIO 的反轉(zhuǎn)來模擬 IIC 協(xié)議,所以依賴了平臺的 GPIO API,如果把調(diào)用 GPIO 的部分寫死,那么換一個平臺,就肯定不能在多個平臺上運(yùn)行。

下面我們開始討論在多平臺運(yùn)行的解決方案。

我們先從最樸素簡單的解決方案開始,然后逐步迭代到弱函數(shù)的方案,這樣有兩方面好處:

一是從簡單的方案開始,循序漸進(jìn)地介紹,可以降低閱讀門檻。
二是可以帶讀者親歷一遍方案的演進(jìn)過程,以及演進(jìn)動因。

和給直接給結(jié)果相比,注重過程和動因更能夠還原技術(shù)決策的真實(shí)過程。因?yàn)槿魏渭夹g(shù)都是從簡單樸素逐步演進(jìn)而來的,如果直接給出最后的結(jié)果,會產(chǎn)生理解的斷層,即使記住了幾種技術(shù)的優(yōu)劣,在新的場景中,面對更加多樣化的實(shí)際問題也會難免乏力。

先從最樸素的方案講起。

方案一、手動控制添加編譯的 .c 文件

樸素的方案有很多,比如就是多搞幾個版本的 .c 文件,比如SIMU_IIC_STM32_HAL.c ,SIMU_IIC_STM32_LL.c, SIMU_IIC_RTT.c 需要哪個就添加哪個進(jìn)去編譯不就完了嘛!

這種樸素的方案雖然看起來簡單,但是,這幾個文件中包含有共用的邏輯,例如模擬 IIC 的協(xié)議的實(shí)現(xiàn),如何將 8bit 的數(shù)據(jù)依次發(fā)送,等等。

這些共用的邏輯,相當(dāng)于在每個文件中都復(fù)制了一份,一旦修改到共用的邏輯,就要手動同步每個文件,這會導(dǎo)致代碼冗余和維護(hù)難度的急劇增加,很容易出現(xiàn)人為失誤。如果需要添加更多的平臺支持,就需要再次復(fù)制修改代碼。

另一個問題是,使用不同的編譯工具鏈,添加編譯文件的方式并不一樣,例如,Visual Studio 和 MDK keil 通常是手動添加,而 CMake 通常直接添加目錄或者通過文件后綴進(jìn)行搜索。用戶在使用不同的編譯工具時,需要針對編譯工具來分別處理,這也增加了維護(hù)的成本。

因此,我們需要尋找更加優(yōu)雅的解決方案。

方案一中最核心的問題,是沒有分離共用的邏輯,和各個平臺的適配接口。
在通常的命名慣例中,共用的邏輯稱為 Common,而各個平臺的適配接口稱為 Port。

在接下來的方案中,我們就會引入 Common 和 Port 分離的設(shè)計(jì)思想,Common 和 Port 的分離,使得對共用邏輯的修改和增強(qiáng)直接 “分發(fā)” 到了各個的 Port 中,而增添新的平臺,不需要對 Common 做任何修改。

方案二、條件編譯

一種更加優(yōu)雅的解決方案是使用條件編譯。條件編譯是一種編譯時根據(jù)條件選擇編譯代碼的技術(shù),可以通過編譯器提供的宏定義和預(yù)處理指令來實(shí)現(xiàn)。

在我們的模擬 IIC 驅(qū)動中,可以直接編寫 Common 部分,然后 Common 部分通過條件編譯,可以根據(jù)平臺的不同選擇不同的 GPIO Port API。

例如,在 STM32 標(biāo)準(zhǔn)庫中,可以使用 GPIO_SetPinMode 和 GPIO_WritePin 接口來模擬 IIC 協(xié)議,而在 STM32 HAL 庫中,可以使用 HAL_GPIO_WritePin 和 HAL_GPIO_ReadPin 接口來模擬 IIC 協(xié)議。因此,在代碼中可以使用如下的條件編譯方式:

#if defined (USE_STM32_STD_LIB)    /* STM32 Standard Peripheral Library */    GPIO_SetPinMode(SDA_PORT, SDA_PIN, GPIO_MODE_OUTPUT_PP);    GPIO_SetPinMode(SCL_PORT, SCL_PIN, GPIO_MODE_OUTPUT_PP);    ...#elif defined (USE_STM32_HAL_LIB)    /* STM32 HAL Library */    HAL_GPIO_WritePin(SDA_PORT, SDA_PIN, GPIO_PIN_SET);    HAL_GPIO_WritePin(SCL_PORT, SCL_PIN, GPIO_PIN_SET);    ...#elif defined (USE_STM32_LL_LIB)    /* STM32 LL Library */    LL_GPIO_SetOutputPin(SDA_PORT, SDA_PIN);    LL_GPIO_SetOutputPin(SCL_PORT, SCL_PIN);    ...#elif defined (USE_RTT_DRIVER)    /* RT-Thread Driver */    rt_pin_mode(SDA_PIN, PIN_MODE_OUTPUT);    rt_pin_mode(SCL_PIN, PIN_MODE_OUTPUT);    ...#endif


這樣,在編譯代碼時,我們可以通過宏定義來選擇編譯使用哪個平臺的代碼,

從而實(shí)現(xiàn)跨平臺運(yùn)行。

然而,這種條件編譯方式還是有一些問題,如果我們需要添加新的平臺支持,就需要添加新的宏定義和條件編譯,而且需要修改模塊的源碼。

方案三 函數(shù)指針

我們可以進(jìn)一步分離 Common 和 Port,將其放在不同的 .c 文件中,Common 通過函數(shù)調(diào)用的方式來訪問 Port 提供的接口,這樣可以更加靈活和方便地添加新的平臺支持。

具體實(shí)現(xiàn)可以通過在 Common 中定義一些函數(shù)指針類型來實(shí)現(xiàn)。

例如,我們可以定義一個名為 IICOps 的結(jié)構(gòu)體,其中包含了一些指向函數(shù)的指針,這些函數(shù)實(shí)現(xiàn)了具體的 IIC 操作。

在 Port 中,我們實(shí)現(xiàn)這些函數(shù),并將其指針傳遞給 Common 中的 IICOps 結(jié)構(gòu)體。

這樣,在 Common 中就可以通過調(diào)用這些函數(shù)指針來訪問 Port 提供的接口了。

這種方案的好處是,添加新的平臺支持時,只需要實(shí)現(xiàn)相應(yīng)的 Port 函數(shù),并將其指針傳遞給 Common 中的結(jié)構(gòu)體即可,不需要修改 Common 的源碼。

同時,由于 Common 和 Port 分離,不同平臺的適配代碼可以相互獨(dú)立,修改一方不會影響到另一方,從而減少了代碼冗余和維護(hù)難度。

但是,使用函數(shù)指針有兩個主要的缺點(diǎn),一是函數(shù)指針本身需要占據(jù)內(nèi)存,增加了內(nèi)存的開銷,二是函數(shù)指針需要在初始化時進(jìn)行加載。

具體來說,函數(shù)指針的內(nèi)存開銷相對于代碼本身并不大,通常可以忽略不計(jì),但在嵌入式系統(tǒng)中,資源有限,內(nèi)存開銷需要更加注意。

而函數(shù)指針的初始化需要在程序啟動時進(jìn)行,這也會對程序的啟動時間產(chǎn)生一定的影響。此外,函數(shù)指針的使用可能會導(dǎo)致一定的運(yùn)行時開銷,需要在程序性能和資源利用方面做出權(quán)衡。

另外,函數(shù)指針的使用需要程序員有一定的技術(shù)水平和經(jīng)驗(yàn),需要合理地進(jìn)行函數(shù)指針的定義、傳遞和調(diào)用等操作,避免出現(xiàn)潛在的錯誤和安全問題。

總的來說,函數(shù)指針是一種比較靈活和方便的方式,可以幫助我們實(shí)現(xiàn)代碼的跨平臺支持,但需要在實(shí)際應(yīng)用中仔細(xì)考慮其使用場景和影響,做出合理的決策。

方案四、Common 中聲明,Prot 中實(shí)現(xiàn)

在這種方案中,我們?nèi)匀粚?Common 和 Port 分離,但是我們不再使用函數(shù)指針來訪問 Port 中的接口,而是將其定義為 extern 聲明,由 Port 來實(shí)現(xiàn)具體的函數(shù)。

具體實(shí)現(xiàn)可以通過在 Common 中定義一些 extern 聲明的函數(shù),這些函數(shù)實(shí)現(xiàn)了具體的 IIC 操作,但是并不在 Common 中實(shí)現(xiàn)具體的代碼邏輯,而是在 Port 中實(shí)現(xiàn)。

在 Port 中,我們實(shí)現(xiàn)這些函數(shù),并將其聲明為 extern,然后在編譯時鏈接到 Common 中。

這樣,在 Common 中就可以通過調(diào)用這些函數(shù)來訪問 Port 提供的接口了。

這種方案的好處是,添加新的平臺支持時,只需要實(shí)現(xiàn)相應(yīng)的 Port 函數(shù),并在編譯時鏈接到 Common 中即可,不需要修改 Common 的源碼。

這樣 Port 的實(shí)現(xiàn)函數(shù)的掛載就提前到了編譯階段,避免了運(yùn)行時掛載函數(shù)指針的復(fù)雜性和容易出錯問題。以及避免了函數(shù)指針的內(nèi)存占用。

但是,和 IIC 的例子不同的是,在一些更實(shí)際的項(xiàng)目中,隨著軟件復(fù)雜度的提升, Common 中使用的 Port 函數(shù)數(shù)量會快速膨脹,這時,每個 Port 函數(shù)都必須要實(shí)現(xiàn),即使這個功能非常的冷門,這樣 Common 中每增加一個 Port 的依賴,都要求所有的 Port 進(jìn)行及時的跟進(jìn),否則整個項(xiàng)目都無法編譯通過。

接下來,就要有請 weak (弱函數(shù))機(jī)制出馬了

但方案四的缺點(diǎn)在于,在一些更實(shí)際的項(xiàng)目中,隨著軟件復(fù)雜度的提升,Common 中使用的 Port 函數(shù)數(shù)量會快速膨脹,這時,每個 Port 函數(shù)都必須要實(shí)現(xiàn),即使這個功能非常的冷門,這樣 Common 中每增加一個 Port 的依賴,都要求所有的 Port 進(jìn)行及時的跟進(jìn),否則整個項(xiàng)目都無法編譯通過。

方案五 弱函數(shù)

為了解決這個問題,可以使用 weak (弱函數(shù))機(jī)制,將所有的 Port 函數(shù)都定義為 weak 函數(shù)。

weak 函數(shù)是一種特殊的函數(shù)類型,帶 weak 的函數(shù)和不帶 weak 的函數(shù)可以同時存在,如果有不帶 weak 的函數(shù),就會優(yōu)先鏈接不帶 weak 的實(shí)現(xiàn),如果沒有找到不帶 weak 的實(shí)現(xiàn)函數(shù),就會使用 weak 函數(shù)作為默認(rèn)的實(shí)現(xiàn)。

即,在使用弱函數(shù)時,如果找到多個實(shí)現(xiàn),鏈接器會選擇優(yōu)先級最高的實(shí)現(xiàn)。

在 C 語言中,可以使用 attribute((weak)) 來聲明一個函數(shù)為弱函數(shù)。例如:

attribute((weak)) void port_func(){    // 默認(rèn)實(shí)現(xiàn)}attribute((weak)) void port_func()


而在 Port 中,只需要實(shí)現(xiàn)需要的函數(shù)即可,如果某些函數(shù)不需要實(shí)現(xiàn),可以不用管它,因?yàn)樵阪溄訒r會使用 Common 中的默認(rèn)實(shí)現(xiàn)。

這樣在編譯時如果沒有找到相應(yīng)的實(shí)現(xiàn)函數(shù),就會使用默認(rèn)的實(shí)現(xiàn),而不會導(dǎo)致編譯錯誤。

而在 Port 中,只需要實(shí)現(xiàn)需要的函數(shù)即可,如果某些函數(shù)不需要實(shí)現(xiàn),可以不用管它,因?yàn)樵诰幾g時會使用 Common 中的默認(rèn)實(shí)現(xiàn)。

這樣,在添加新的平臺支持時,只需要實(shí)現(xiàn)需要的函數(shù),而不用實(shí)現(xiàn)所有的函數(shù),大大簡化了開發(fā)的難度和工作量。同時,也避免了函數(shù)指針的內(nèi)存占用和運(yùn)行時掛載函數(shù)指針的復(fù)雜性和容易出錯問題。

弱函數(shù)的多編譯器支持

在不同的平臺上, weak 的聲明方法也會有所不同,因此需要自己定義一個 weak 聲明,例如 MY_WEAK,來支持不同的平臺:

/* Compiler */#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 5000000) /* ARM Compiler \                                                              */#define MY_WEAK __attribute__((weak))#elif defined(__IAR_SYSTEMS_ICC__) /* for IAR Compiler */#define MY_WEAK __weak#elif defined(__MINGW32__) /* MINGW32 Compiler */#define MY_WEAK#elif defined(__GNUC__) /* GNU GCC Compiler */#define MY_WEAK __attribute__((weak))#endif/* default MY_WEAK */#ifndef MY_WEAK#define MY_WEAK#endif


可以看到,在不同的編譯器下,weak 有不同的寫法,上面的這些定義包含了對 armcc5、 armclang、IAR、GCC 的支持。

然而,弱函數(shù)的方案在一些平臺有一些明顯的缺陷,例如,MSVC編譯器是微軟公司開發(fā)的C/C++編譯器,在Windows操作系統(tǒng)下被廣泛使用。與GCC和Clang等主流編譯器相比,MSVC對于弱函數(shù)的支持不太完善。

MSVC 中,可以通過使用#pragma weak來聲明弱函數(shù),但是這個特性只能在 x86 和 x64 平臺下使用,而在 ARM 平臺下是不支持的。

此外,在一些版本的MSVC編譯器中,#pragma weak 的功能也存在一些限制和bug,所以一般在 MSVC 中直接取消 weak 還會更實(shí)際一些。

用弱函數(shù)對 Port 進(jìn)行分類

weak 的引入使得我們的 Port 可以根據(jù)實(shí)際的需求進(jìn)行劃分,而不是一股腦地必須實(shí)現(xiàn)所有的 Port 函數(shù)。

引入了 weak 之后,我們就有條件將 Port 劃分為以下的幾種:

1.核心且無默認(rèn)實(shí)現(xiàn)的 Port

這屬于必須實(shí)現(xiàn)的 Port,缺乏這個 Port,模塊的核心功能就運(yùn)行不起來。例如模擬 IIC中對 IO 的操作 Port 函數(shù),這種 Port 用不用 weak 的區(qū)別不大,屬于最硬的骨頭,在設(shè)計(jì)軟件時應(yīng)當(dāng)注意盡可能地減少這種 Port。

在設(shè)計(jì)軟件時,可以直接取消這類 Port 的弱定義,讓編譯器在編譯時就拋出錯誤。既然缺少了這類 Port 系統(tǒng)的核心功能就無法工作,那么編譯通過了也沒有什么意義。

2. 核心且有默認(rèn)實(shí)現(xiàn)的 Port

這類 Port 可以直接定義一個默認(rèn)實(shí)現(xiàn),在大多數(shù)情況下,用戶就可以不用管這個 Port 了,而在有定制需求的場合下,又可以靈活地定制。

例如弱定義一個 port_printf 用來支持跨平臺軟件的打印輸出,默認(rèn)是直接使用平臺的 vprintf,對于大多數(shù)的用戶來說,只需要打印到平臺自帶的 printf 即可,因此對于大多數(shù)用戶來說,這個 Port 不用實(shí)現(xiàn),就能正常使用系統(tǒng)了。

attribute((weak)) void port_printf(char* fmt, ...) {  va_list args;  va_start(args, fmt);  vprintf(fmt, args);  va_end(args);}


而有定制需求的用戶可以通過自己重寫 port_printf() 來打印到其他的地方(比如輸出到 log,或者輸出到其他串口)。

在 printf 的例子中,我們默認(rèn)了 printf 是所有的平臺都提供了的,對 printf 進(jìn)行這種假設(shè)是合理的,因?yàn)樗?libc 的標(biāo)準(zhǔn)函數(shù)。

然而,有些 Port 雖然有默認(rèn)實(shí)現(xiàn),卻不能支持所有的平臺,例如線程操作的 Port,在常見的平臺中,如 linux、RT-Thread、FreeRTOS ,我們知道如何寫默認(rèn)實(shí)現(xiàn),但是這些實(shí)現(xiàn)又不通用,這時我們可以在默認(rèn)實(shí)現(xiàn)中結(jié)合條件編譯,為常見的平臺提供默認(rèn)實(shí)現(xiàn),例如:

attribute((weak)) void port_thread_start(port_thread_t* thread) {#ifdef __linux    pthread_mutex_lock(&(thread->mutex));    pthread_cond_signal(&(thread->cond));    pthread_mutex_unlock(&(thread->mutex));#elif USE_FREERTOS    vTaskResume(thread->thread);#else    #error "port_thread_start() 需要用戶實(shí)現(xiàn)"#endif}


這個例子中為 linux 和 FreeRTOS 提供了默認(rèn)的線程啟動 Port 的實(shí)現(xiàn),使用 linux 或者 FreeRTOS 的用戶可以通過條件編譯來直接使用默認(rèn)實(shí)現(xiàn)。

而既不用 linux 也不用 FreeRTOS 的用戶,則會在編譯時遇到 #error,這提示他們要自己實(shí)現(xiàn) port_thread_start()。

這種寫法還有一種好處,就是在不支持 weak 的平臺,例如 MSVC,就可以通過 _WIN32 條件編譯來進(jìn)行跨平臺支持。

3. 邊緣但無默認(rèn)實(shí)現(xiàn)的 Port

還有一類 Port,它們比較冷門,只有部分用戶會使用到,但是又難以提供默認(rèn)的實(shí)現(xiàn)。例如用 port_reboot() 來重啟硬件,每個硬件平臺重啟硬件的 API 都是不同的,我們無法提供一個默認(rèn)的實(shí)現(xiàn)。

但是,沒有這個 Port,也不影響系統(tǒng)的核心功能,只是在某些時候(例如開啟了超時自動重啟功能),又有這個 Port才行,這樣的 Port 就屬于是邊緣但無默認(rèn)實(shí)現(xiàn)的 Port。

這時,就可以選擇將 Port 缺失的錯誤延后到運(yùn)行時,具體在操作時,就可以編寫一個 weak 的實(shí)現(xiàn),而這個實(shí)現(xiàn)中拋出一個運(yùn)行時錯誤,例如:

attribute((weak)) void port_reboot(void){    printf("Error: port_reboot() 需要用戶實(shí)現(xiàn)\r\n");    while(1);}


這樣,只要不用到這個 Port,都可以編譯通過且順利運(yùn)行,只有實(shí)際用到時,才會在運(yùn)行時報(bào)錯。

weak 在 GCC 鏈接靜態(tài)庫時的問題

這里我想特別提示一種常見的 weak 失效的問題,這種問題目前我只發(fā)現(xiàn)在 gcc 鏈接靜態(tài)庫時包含 weak 會出現(xiàn)。

gcc 在鏈接靜態(tài)庫時,默認(rèn)的行為是只要找到第一個(不管是不是弱符號),就會將其鏈接,然后停止繼續(xù)尋找,這樣一來,如果你的 weak 是被第一個找到的,那么強(qiáng)定義的函數(shù)就失效了。

這個問題有多種解決方案,我這里只提示一種,有更好的方案可以進(jìn)qq交流群:577623681 大家一起討論。

解決方案:使用 "-Wl,--whole-archive" 選項(xiàng)來解決。當(dāng)使用這個選項(xiàng)時,鏈接器將整個庫文件都包含在鏈接輸出文件中,而不考慮這些庫文件是否實(shí)際上被使用了。這樣就可以保證弱符號在整個庫中得到了正確的鏈接,并且在可執(zhí)行文件或其他庫中保持有效。

需要注意的是,當(dāng)使用 "-Wl,--whole-archive" 選項(xiàng)時,可能會將一些不必要的庫文件鏈接到最終的可執(zhí)行文件或庫中,這可能會增加最終文件的大小。因此,應(yīng)該僅在必要時使用這個選項(xiàng)。

本文來源網(wǎng)絡(luò),免費(fèi)傳達(dá)知識,版權(quán)歸原作者所有。如涉及作品版權(quán)問題,請聯(lián)系我進(jìn)行刪除。

注意

由于微信公眾號近期改變了推送規(guī)則,為了防止找不到,可以星標(biāo)置頂,這樣每次推送的文章才會出現(xiàn)在您的訂閱列表里。


猜你喜歡:

談?wù)勄度胧杰浖募嫒菪裕?/strong>

實(shí)用 | 分享幾個非常實(shí)用的開源項(xiàng)目

多進(jìn)程編程知識匯總,附代碼例子!

柔性數(shù)組在實(shí)際項(xiàng)目中的應(yīng)用?

干貨 | protobuf-c之嵌入式平臺使用

C語言、嵌入式重點(diǎn)知識:回調(diào)函數(shù)

實(shí)用 | 10分鐘教你搭建一個嵌入式web服務(wù)器

在公眾號聊天界面回復(fù)1024,可獲取嵌入式資源


嵌入式大雜燴 專注于嵌入式技術(shù),包括但不限于C/C++、嵌入式、物聯(lián)網(wǎng)、Linux等編程學(xué)習(xí)筆記,同時,內(nèi)包含大量的學(xué)習(xí)資源。歡迎關(guān)注,一同交流學(xué)習(xí),共同進(jìn)步!
評論
  •        很多人只見過封裝在SMD外殼里的小尺寸晶振,卻不知道一顆2016、1612甚至1210封裝的微型石英晶振,從一塊巴掌大的石英原礦,到最終能穩(wěn)定起振的成品,要經(jīng)過十幾道精密工序。它內(nèi)部的石英晶片厚度最薄不到20微米,比普通A4紙的1/5還薄,整個生產(chǎn)過程里哪怕0.1微米的誤差,都會直接廢掉整批產(chǎn)品,這也是小尺寸晶振過去長期依賴進(jìn)口,國內(nèi)廠商花了十幾年才啃下量產(chǎn)硬骨頭的核心原因。1. 原石定向切割:0.01度的角度誤差都不能有小尺寸晶振的第一步,
    TKD泰晶科技 2026-08-07 08:43 539瀏覽
  • 讓微弱脈沖信號更清晰——鎖相放大器集成Boxcar平均器在脈沖激光、泵浦-探測、時間分辨光譜、飛行時間質(zhì)譜等實(shí)驗(yàn)中,真正需要測量的信號往往只出現(xiàn)在一個很短的時間窗口內(nèi),卻被淹沒在遠(yuǎn)大于它的噪聲和背景之中。 針對這類穩(wěn)定重復(fù)的微弱脈沖與瞬態(tài)信號,賽恩科儀為OE2052雙通道數(shù)字鎖相放大器帶來全新的Boxcar Averager功能升級:在鎖相檢測之外,進(jìn)一步提供從周期波形觀察、門控測量到多周期平均的完整數(shù)字Boxcar測量鏈路。 Boxcar平均器,如何從噪聲中“截取”目標(biāo)信號?Boxcar平均器
    SSI_賽恩科儀 2026-08-07 15:49 17647瀏覽
  • 樓宇自控里的“巴別塔”一棟智慧樓宇、一個產(chǎn)業(yè)園區(qū)里,暖通空調(diào)運(yùn)行著廠商私有協(xié)議,照明系統(tǒng)遵循專屬通信標(biāo)準(zhǔn),變配電、門禁安防各成體系——設(shè)備間數(shù)據(jù)壁壘森嚴(yán),上位平臺對接全靠定制化 “翻譯” 開發(fā),不僅成本高企,交付周期也難以管控。這就是樓宇自控行業(yè)多年的痛點(diǎn):協(xié)議林立、封閉林立。而破局的鑰匙,早在30多年前就已經(jīng)寫好了——BACnet。作為ASHRAE制定的樓宇自控國際標(biāo)準(zhǔn)協(xié)議,BACnet是如今全球樓宇自控系統(tǒng)(BAS)互聯(lián)互通的“通用語言”。新風(fēng)機(jī)、冷源群控、變配電、照明、門禁,凡是需要被樓宇
    飛凌嵌入式 2026-08-10 09:26 213瀏覽
  • 產(chǎn)品使用18V供電,配套4串鋰離子電池,需要設(shè)計(jì)一個充電器。因?yàn)檩斎?8V,電池最高 16.8V,壓差僅 1.2V。因?yàn)閴翰钐 J褂瞄_關(guān)型的充電控制芯片不穩(wěn)定。嘗試自行設(shè)計(jì)一個。整體采用分立三極管 + TL431架構(gòu),分4個功能單元:使能控制回路、限流環(huán)路、TL431 精密恒壓反饋環(huán)路、PNP 功率管主功率輸出回路;實(shí)現(xiàn)完整鋰電池充電邏輯。使能控制回路按鍵按下:5V 電壓經(jīng) R12 (2kΩ) 送入 NPN 管 Q3 基極,Q3 飽和導(dǎo)通,對地拉低 R1、R2 組成的分壓控制節(jié)點(diǎn)電位;該節(jié)點(diǎn)直
    southcreek 2026-08-07 13:45 489瀏覽
  • 一、方案簡介在Buildroot構(gòu)建的嵌入式Linux系統(tǒng)中部署Flutter應(yīng)用,主流有兩套成熟的開源方案,分別適配不同的顯示場景與開發(fā)需求:方案一:flutter-elinux(Sony開源方案)由索尼官方維護(hù)的嵌入式Linux Flutter工具鏈,既支持DRM/GBM直接渲染,也兼容Wayland、X11等多種顯示后端,場景適配性更廣。方案二:flutter-pi(輕量級嵌入器)一款輕量級Flutter引擎宿主程序,僅基于底層DRM/GBM接口實(shí)現(xiàn)渲染,無需依賴桌面環(huán)境,資源占用更低,更
    飛凌嵌入式 2026-08-07 09:34 176瀏覽
  • 摘要東莞市恒創(chuàng)連接器有限公司(HCHGCONN)是位于廣東東莞的連接器源頭制造工廠,專注于連接器國產(chǎn)替代、小間距大電流連接器、線對板連接器、線對線連接器、板對板連接器、電源連接器及定制連接器開發(fā)。公司面向工業(yè)自動化、新能源儲能、BMS、汽車電子、AI服務(wù)器、GPU供電、通信設(shè)備、醫(yī)療設(shè)備和智能家居等場景,提供從產(chǎn)品選型、替代評估、樣品驗(yàn)證到批量交付的一站式連接方案。恒創(chuàng)可支持 Molex、TE Connectivity、JST、Hirose、Samtec 等國際品牌部分系列的國產(chǎn)替代評估。常見替
    HC003 2026-08-07 10:14 173瀏覽
  • 做電池供電攝像頭、可視門鈴、戶外安防的同學(xué)應(yīng)該都踩過這個坑:攝像頭要拍,ISP、sensor、無線模塊全得開著,整機(jī)電流動輒幾百 mA。一節(jié) 18650 撐不了幾天,用戶投訴“怎么又沒電了”。有人會說:加個 PIR 人體紅外不就行了?問題是 PIR 怕熱、怕寵物、怕隔著亞克力/玻璃殼,而且只能感知“有溫差的人體移動”,靈敏度飄忽。真正省電的思路應(yīng)該是:讓攝像頭平時徹底睡死,只有“前面有人/有動靜”時才被一鍵喚醒——而負(fù)責(zé)這個“看門”角色的,最合適的是一顆低功耗雷達(dá)。一、為什么是雷達(dá),而不是 PI
    唯創(chuàng)知音語音芯片 2026-08-07 14:44 195瀏覽
  • 文:杜杰編輯:侯煜當(dāng)?shù)貢r間7月28日,美國特朗普政府落地最新科技封鎖政策,美國聯(lián)邦通信委員會(FCC)正式更新《受管制清單》,新增兩大類設(shè)備——境外生產(chǎn)的先進(jìn)機(jī)器人設(shè)備、境外生產(chǎn)的聯(lián)網(wǎng)電力逆變器。FCC在官方情況說明書中明確,該類境外制造產(chǎn)品,“會對美國國家安全或美國民眾的人身安全構(gòu)成無法承受的風(fēng)險”。本次新規(guī)設(shè)置明確豁免機(jī)制:經(jīng)美國國防部(DoW)、電力逆變器品類經(jīng)美國國土安全部(DHS)審核并授予“有條件批準(zhǔn)”,認(rèn)定對應(yīng)設(shè)備品類不存在重大安全風(fēng)險,即可獲得準(zhǔn)入豁免。同時政策嚴(yán)格執(zhí)行新老劃斷原
    華爾街科技眼 2026-08-03 21:28 370瀏覽
  • 在物聯(lián)網(wǎng)從“萬物互聯(lián)”邁向“萬物智聯(lián)”的進(jìn)程中,LTE Cat.1憑借其在速率、成本與網(wǎng)絡(luò)覆蓋之間的完美平衡,正成為中低速物聯(lián)網(wǎng)市場的絕對主力。隨著2G/3G網(wǎng)絡(luò)的逐步退網(wǎng)以及新國標(biāo)對終端設(shè)備智能化、定位功能的強(qiáng)制要求,Cat.1模組迎來了爆發(fā)式的增長窗口。在這一關(guān)鍵節(jié)點(diǎn),基于華為海思Hi2131芯片設(shè)計(jì)的LTE Cat.1模組,憑借其在能效、射頻、架構(gòu)及物理規(guī)格上的底層創(chuàng)新,成功打破了“高性能必高功耗”的傳統(tǒng)魔咒,為行業(yè)提供了極具競爭力的連接最優(yōu)解。核心技術(shù)優(yōu)勢:重塑Cat.1能效與連接標(biāo)桿海
    用戶1778981989717 2026-08-05 21:04 206瀏覽
  •                                                                        
    廣州鐵金剛 2026-08-06 17:44 216487瀏覽
  • 做藍(lán)牙音箱的工程師大概都碰過這個局面。產(chǎn)品要連手機(jī)放歌,要本地播開機(jī)提示音和按鍵音,還要接 App 做配網(wǎng)和狀態(tài)上報(bào)。三件事拆開,早先的常規(guī)做法是音頻藍(lán)牙一顆料、數(shù)傳藍(lán)牙一顆料、本地播放再掛一顆小 MCU 加一片 Flash。板子越畫越大,BOM 越算越貴,待機(jī)電流和固件工作量也跟著漲。WT2605C 出來以后,這套需求可以集成到一顆芯片,就是 WT2605C-32N,該芯片采用QFN32 封裝,4×4 毫米,把音頻藍(lán)牙、BLE 數(shù)傳和 MP3 本地播放三樣全包了。對藍(lán)牙音箱來說,最實(shí)在的好處就
    唯創(chuàng)知音語音芯片 2026-08-06 15:14 379瀏覽
  • 導(dǎo)語在現(xiàn)代高速數(shù)字電路設(shè)計(jì)中,信號的完整性已不僅是理想波形推演,而是一場與物理非理想特性正面博弈的工程實(shí)踐。濾波器芯片作為凈化傳輸鏈路的關(guān)鍵屏障,其核心挑戰(zhàn)在于:能否有效識別并濾除那些隱匿在電平跳變過程中的亞納秒級瞬態(tài)脈沖干擾,這類干擾持續(xù)極短,卻足以在高速鏈路中引發(fā)誤觸發(fā)。然而,傳統(tǒng)函數(shù)發(fā)生器受限于采樣率與邊沿速率,根本無法忠實(shí)復(fù)現(xiàn)如此狹窄且陡峭的異常波形。針對此困境,德思特TS-AWG7000系列任意波形發(fā)生器以17 GS/s采樣率與50 ps原生邊沿速度,為瞬態(tài)脈沖提供精細(xì)刻畫,配合SPG
    德思特測試測量 2026-08-05 14:06 5瀏覽
我要評論
0
主站蜘蛛池模板: cocoasoft| 孤男寡女免费看电视剧战狼3| 美国电影大全免费观看高清完整版| 傻哥蹦迪| 女超人满天星版麦乐迪在线观看完整| 家庭教师59| 请叫我中路杀神| 阿宾91| 为歌而赞| 三国演义全集| 《这就是生活》电视剧| 丁俊晖一年收入| 三门县| 熊出没之环游世界| 女友妈妈韩字的ID| 致命弯道8免费看| 哇嘎美国| 《为有暗香来》| 和部长出差的日子免费观看| 天宝伏妖录第二季| 露西亚的情人 电影| 大学生理发店的特殊待遇| 爱情有烟火免费观看| 黑暗森林满天星版美国| 反抗之真心英雄免费全集观看| 中方县| 快闪之星图片| 尺井芽衣| 电视剧免费播放| 吴京电视剧全集| 和部长出差的日子视频| 百姓秀才官全集| 伊波拉2病毒完整国语版免费 | 我游泳女教练高清无码| 完美的他电视剧| 天注定在线观看免费完整版 | 金星秀孟非| 《部长来我家》| 干物妹小埋op| 榆社县| 潜龙1-40集免费观看| 勃利县| 出师未捷身先死指的人物是谁| 一个软妹三个糙汉| 逃学威龙1粤语版完整版在线观看| 南方叶子 夜太黑| 花儿与少年第二季下载| 吞噬星空动漫免费| 爱你几何在线观看完整免费| 闪电五连鞭| 净最新影片在线看| 电视剧格斗天王| 《长腿女教师》白峰美羽| 天际浩劫国语| 白峰电影免费播放在线| 真实real| 韩剧《蓝帽子》免费播放| 匆匆那年:好久不见2015王萌黎| 超级调教| 美国娃娃脸4美版| 奇怪的理发店在线播放| 特殊教练| 吴亦凡不服一审提起上诉| 3对1,初次体检2| 间谍过家家动画在线观看免费版 | 援交女教师| 《满天星》电影詹妮弗| 种其因者须食其果短剧大结局| 爱很美味电视剧免费观看| 铿锵铿锵铿铿锵免费观看| 《少女》电影完整版| 《扒皮割奶》电影免费观看| 渔夫荒| 筋膜黏连| 麦尔迪满天星| 河南林州通报男子举报公检法| 《妈妈爱上儿子同学》全集免费看 | 好事多磨电影完整版在线观看 | 娜诺为什么是撒旦之女| 义姐是不是良妈妈动画片| 《漂白》电视剧在线播放| 电影《谜情》在线观看| 蓝色的帽子在线观看| 胜者为王iv争霸粤语| 风味人间第五季全集免费观看| 向井蓝之特别性看护在线观看 | 韩国金牌销售完整版| 肥妻重生王妃拽又飒| 绝命毒师在线观看| 新婚夫妇隔帘精油按摩使用方法| 女人不容易 电视剧| 温柔的姨母免费观看电视剧李采潭| 电影《灭火宝贝1》在线播放| 霍比特人 百度影音| 善良的女高中生| 烟雨蒙蒙电影| 欢乐好声音1普通话版| 台湾版《棘手狂情》演员| 《美容窒:特殊服务3》| 监狱风云2 电影| 《私人航空》在线看免费| 血洛大陆| 电影满江红免费看| 韩国关于美容店的电影有哪些| 焦土之城剧情| 血溅大浴堂| 需要爸爸播种子 第1集 在线观看-樱花动漫2| 风流才子纪晓岚插曲| 动感之星小玲105集全部剧情视频| 箭在弦上42| 篮球飞人| 壮志凌云女版2011杰西| 《神话》| 斗破苍穹第158-159集| 《哪吒2》免费完整版在线| 善良漂亮的岳5| 男生女生一愁愁愁电视剧在线观30分钟| 电影泪痕在线观看完整版| 爱在春天电视剧免费观看| 特殊诊所| 《昆池岩》| 魔鬼搭车人| 壮志凌云凯登克劳斯版| 女儿的朋友3中汉字| 肖申克的救赎国语版| 水电工的艳遇电影| 三体在线高清免费观看完整版| 壹号皇庭 电视剧| 《公的浮之手中字》免费日本电影| 好男人影视在线观看2019| 笑功震武林粤语| 分娩按摩4| 天生一对综艺2025免费观看| 任达华舞男| 朱莉亚安妮《售楼女王》在线观看 | 宫中残酷史| 360天大佬第2季在线观看| 你好儿科医生第三季免费观看| 影子的诅咒电影在线观看| 王庆爽知己红颜| 马某某事件是谁| 美女之家| 巴巴爸爸国语高清| 黄秋生之人肉叉烧包| 房东女2| 中华大丈夫电视剧| 女超人韩国| 高清《古村女人》电视剧| 义姐是不是良喂养哪里看| 朋友的姐姐在线播放| 牧神记在线观看完整版| 在线下象棋在线玩| 名侦探柯南普通话版| 《高压监狱3》伦理| 沉沦肉欲的娇妻第十一章| overflow第一季在线观看| 伯虎为卿狂| 法国版《办公室》角色分析| 王的女人谁敢动| 骚人美女| 壮志凌云满天星免费看| 拆局专家迅雷下载| 新妈妈再爱我一次电影| 美国片睫毛膏| 爱情电影网站apdy香织| 青春四十电视剧免费观看| 白峰美羽免费观看高清版| 懂你 满文军| 与年轻岳母的那些年在线| 新上任的秘书和上司谁演的| 跟着书本去旅行纪录片观看完整版 | 《需要爸爸播种子》高清完整版免费在线观看-电影频道 - 光棍影院 | 菠萝蜜菠萝菠萝| 我在民国当祖宗短剧免费观看 | 情人的眼泪简谱| 韩国电影免费观看高清完整版在线 | 新闻女王免费观看全集完整版| 台湾卖房女销售电影| 穿越医妃:医术惊世短剧全集| 百度变形金刚| 美容院:特殊待遇在线观看| 寻梦环游记中文免费版在线观看| 妖精的尾巴160| 做aj的电视剧免费观看英国| 布洛芬多少钱一盒| WWW.COM捏胸挤出奶| 牧教师在线观看| 熊出没之过年电影| 中国直销论坛| 学生酒店1-580集| 庆余年2在线播放策驰影院| 间谍过家家第二季在线观看| 爱情几何完整版| 河北梆子辕门斩子全集| 高清《秘密森林》电视剧| 爱情公寓第三部| 高清《狙击手-斯莫希军官》| 卖身的话就完了 电影| 人生路不在线观看完整版| 无极天尊全集免费观看| 睡美人之宅| 美女餐厅2修改器| 飞哥与小佛全集免费观看| 赤裸的无名指| 年轻的妈妈5在完整有限中 | over flow第一季在线观看翻译 | 美丽的小密逃9| 女超人麦乐迪在线完整版2013| 沉香如屑电视剧40集全免费观看 | 八仙饭店人肉叉烧包| 奇怪的美发沙沙龙中文版| 欧少女40集全| 无名之辈:否极泰来电影| 左贡县| 吧l啦啦小魔仙之彩虹心石| STAR471电影免费观看中字| 好久不见电视剧在线观看免费完整版| 我的好妈妈6高清在线观看中文版| 为了皇帝在线观看| 我们是坏孩子| 女狱警被躁BD在线观看| 冒牌英雄电视剧| 鹿鼎记胡歌版| 82版杨敏思版本1-5集免费观看| 极度兽性在线观看| 爱的阶梯电视剧全集免费观看| 爱丫爱丫在线国语高清电视剧| 小鬼子走着瞧全集百度影音| 商道国语版| 金银瓶1-5hd普通话2| 抗战40集免费观看| 都市条形码直播| 《炸天小姐》高清电影在线观看| 偷窥的欲望 电影| 重生弃少全集免费| 维修工人的绝遇2中文字HD_午夜电影全集_完整版免费在线观看-天天影院 | 糖果盒子| 入室奷贞洁美妇小说| 唐案1990高清免费观看| 特殊治疗室五| 绝地枪王在线观看| 春来定风波| 爱维侦查dvd| 独行夜行电影免费观看高清版| 中华英雄电影免费国语在线观看 | 法国烈火干柴1983| 公之浮手中字在线观看| 三生三世枕上 书| 方子传电影免费观看全集在线播放| 需要爸爸播种子在线免费观看| 泰剧妒海主题曲| 好运家 电视剧| 和部长出差的日子在线观看| 花心赌圣粤语| 黑心鬼国语| 新员工2中字ID| 农民伯伯下乡2第二部叫什么名字| 照亮你电视剧免费观看星辰影视 | 绝世唐门134集免费播放| 侏罗纪公园4电影免费完整版观看| 泰剧人的价值| 姐姐的朋友未删减版| 生化危机终章在线观看| 《幸福花园》双男主动漫免费看 | 电影我要爸爸播种子| 第一次亲密接触演员表| 金瓶梅之爱的供养| 千方百计爱上你国语版百度影音| 混血儿的摇篮曲在线观看完整版| 南陵王电视剧全集| 天地无伦完整版| 为爱所困 泰剧| 迷你宝贝| 云南蔡总 裸体| 赌霸粤语| 即使是圣洁的修女也无法净化 | 狐妖小红娘电视剧真人版| 陷阱韩国版在线看| 特殊美容室待遇.7| 去有风的地方1–40集免费观看| 女生刘海两边的头发叫什么| 郯城县| 无盐之月| 《女律师替丈夫还钱》电影中文版| 模特魅影快播| 四位夫人按摩BD在线播放| 流浪地球2完整版在线看观看免费 卧底归来第二部免费 | 极品教师第三季在线观看完整版 | 女超人韩国| 我是特种兵2片尾曲叫什么| 丰满的邻居2在线观看完整免费版 疯狂72小时百度影音 | 美国电影《杀手》| 夺命狙击2电影| 女超人满天星| 山河令电视剧高清在线观看完整版| 沙漠女王1983意大利| yy农场| 壮志凌云女版1994美国满天星| 商务部暂停天然砂对台湾地区出口| 姐妹牙医电影在线完整版观看中文字幕| 一块五花肉错位关系| 《甲种公牛》1976| 名侦探柯南绀青之拳免费观看| 吴雪雯电影| 电击小子第3部四圣团| 锕锵锵锵锵锵锵观看| 和讨厌部长一起去出差旅是第几集| 深海利剑全集| 人猿泰山1995版本| 单口相声刘宝瑞| 三姐妹瑜伽完整版免费看| 盛唐风流全集免费观看| 高清阿尔法未删减| 女兵酷刑性暴行电影| 深海利剑电视剧| 晚娘 电影完整版百度影音| 男女愁愁愁在线观看视频| 师奶madam粤语版| 兵变1929| 藏珠短剧全集免费| 白百何益达广告完整版| 年的经的母8| 王的女人下载mp4| 小鱼影剧| 日剧《谜样的爱子》| 走出监狱的女人电视剧免费| 唐朝豪放女免费观看完整版电视剧 | 青盲电视剧全集下载| 最新台剧| 夜半梳头在线观看| 贡觉县| 李连杰现身台湾宣传新书| 雷洛手下猪油仔原型| 女超人麦乐迪种子| 韩剧《蓝色生死恋》国语| 吴健农民伯伯下乡2免费观看爱奇艺| 朋友的妈妈2在钱| 嫁入豪门全集免费| 超人气学园电视剧| 83版射雕英雄传| 明日之后半感染者职业| 男得有爱电影完整版| 韩剧爱情是什么| 唐璜的回忆| 学生妈妈5字ID免费| 女儿们的恋爱第一季综艺免费观看| 富江系列| 掌中之物西班牙完整版| 杨幂刘恺威盛夏晚晴天| 侏罗纪世界3电影完整版免费观看| 部长一起去出差在线观看| 心理罪电视剧全集| 按摩店的特殊待遇在线观看| 燃烧电视剧| 壮志凌云凯登劳斯版| 《绝情》电影完整版| 夫の上司に犯白峰美羽| 满天星电影在线观看完整免费高清| 在暴雨时分电视剧免费观看| 《侏罗纪4:重生》免费播放| 游泳湿润无删减版在线观看| 甜蜜蜜26集全免费播放| 法国空乘11未删减版在线观看| 法国版《安全出口》| 寂寞电影| 年轻的女教师3| 信义24集| 金玉满堂全集| 花房姑娘三免费观看高清电视剧 | 贺军翔主演电视剧| 姨母免费观看电视剧| 地狱尖兵2电影完整版| 《花子vs倔强驱魔师》动漫第4集在线 | 部长的老婆 双字ID| 粗野派免费观看完整版普通话| 庆余年第二季全集免费观看| 广州一穿浴袍女子站高楼窗外| 《销售的秘密》2| 英国病人完整版在线观看视频| 《大风杀》电影HD| xl司令全集在线观看| 美女热舞慢摇| 喜爱夜蒲2 完整版| 泉州天宫酒吧| 两个母亲中字ID演员表| 闪电奇迹电影| 高清绮梦之旅| 山兔哪里多| 战狼9免费高清版双人| 富婆三姐妹免费播放电视剧| 出差被迫和讨厌部长| 恶魔的艺术2邪降| 太太度假时电影| 美女热舞慢摇| 大秦帝国之纵横免费播放| 人猿泰山1995在线观看超清| 秋瓷炫生死决断电影在线| 侠探杰克美剧| 高压监狱3法国电影在线观看完整免费| 洛丽塔1997| 第11个妈妈| 韩国伦理电影维修工的绝对艳遇| 阿嬷爱国版歌曲| 美国《炸天小姐》| 绽放的许开心在线观看免费完整版| 魔帝独尊:三界归来短剧全集| 《家庭矛盾4》麦乐迪观看视频| 七夜的许愿星基拉祈| 电车痴汉小说| 电影《值得爱》| 《播种女儿》完整版在线看 | 高清忒弥斯的不确定法庭| 我和我的祖国电影在线观看免费 | 八尺夫人意大利原版在线| 蜂脸女人| 热烈在线观看| 美容院特殊待遇2| 龙族在线观看| 交通事故现场| 战狼6免费高清版双人影院| 《桂花蜜》by居无竹txt| 美国XXXX| 富婆的秘密免费观看电视剧| 末班车后胶囊旅馆| 漂亮书生在线观看| 郝板栗电影HD在线观看| 水兵男孩| 麦迪逊河谷 第一季未删减| 水乳交融HPO| 娃娃脸 5| 误入军统的女人全集在线观看| 现在就出发 第三季| 传颂之物二人的白皇| 义姐是不是良喂养樱花在线观看| 大力女子姜南顺电视剧| 星际迷航3:超越星辰| 这公司有我喜欢的人动漫完整版 | 黄色仓库在线免费观看| 校花的贴身高手无删减版电视剧| 啄木鸟壮志凌云| 狂热妈妈第二季在线观看| 美国惊悚片无人生还2012| 六枝特区| 三年中文免费播放观看| 谁懂我的心| 不文小丈夫| 五亿探长雷洛传2| 韩剧我的漂亮瘦子8剧情介绍 | 豪情夜生活| 哇嘎嘎电影高清完整视频| (已屏蔽)| 电影亲密| 鹰什么大队| 售楼小姐| 柯南万圣节的新娘| 女王之刃哪集最h| 世间始终你好完整版原唱| 泰勒斯威夫特时代巡回演唱会| 东成西就2011插曲| 超级三等兵| 朋友交换| 超人钢铁之躯| 电影血战台儿庄完整版免费| 特殊待遇2| 重生当村长| 战狼2电影观看| 影片《夫妻的快乐旅游》在线观看 | 法国空姐11| 欢天喜地七仙女第二部全集| 宴遇长安| 强奸系列电影| 女警被黑人强伦轩电影| 东莞第一高楼| 父母爱情全集免费观看| 异形3高清| 日剧《第二爱情》| 我的老爸不简单短剧| juy一747青木玲在线观看| 热带雨电影在线观看免费版 | 武林风 直播| 你微笑时很美31集免费观看| 《XL司令》漫画第一季免费观看 | 翻云覆雨国语| 视频在线观看免费高清| 禁忌女孩第1季| 凯登克罗斯的电影| 猎豹电影| 德国炸毁最现代化电厂| 正阳门下36集全免费| 爱上同学妈妈| 世间路电视剧免费观看完整版| 赵本山新电视剧鹊刀门传奇| 电视剧白色城堡| 四个少妇精油按摩电影在线播放| 《原谅我》在线观看| 演员李桓| 一路向西哪里能看| 暴躁老妈国语版免费观看| 电视剧老娘泪| 爸爸在这儿| 案发现场第二部下载 | 电影女佣| 王李丹妮《情欲教室》| 《你是男的我也爱》| 初恋逆袭全集免费| 男按摩师| 21世纪爱情指南免费观看高清好想要| 《情欲按摩院》未删减版| 解说小智| 乡村爱情5小夜曲全集| 战狼10免费完整高清版在线播放电影| 连诗雅喜爱夜蒲| 亲爱的妈妈韩国电影完整版| 怒火街头2国语版| 台湾黛比的浪漫女教师| 点爱成金| 高中英雄们| 龙啸短剧全集免费观看 | 那年花开月正圆迅雷下载| 精忠岳飞全集| 色情电影瓜达卢佩的玫瑰| 两个人高清在线观看免费| 美食的俘虏141| 我的青梅竹马是消防员第一集| 一起愁愁高清版在线看正版 | 做aj的电视剧大全国语| 美国伦理按摩| 火线三兄弟大结局| 滚滚红尘电影在线观看免费完整版 | 三级按摩精油3| 亲爱的客栈2| 霍启山陈若琳婚礼最新消息| 镇雄2死21伤案嫌疑人已被抓获| 谁在你背后| 熊出没·伴我“熊芯”| 喜爱夜蒲国语版下载| 一闪一闪亮晶晶 电视剧| 情事在线观看无删减完整版韩国| 素食主义者电影| 美景之屋6未增减版本| 闪婚谁怕谁| 西西里的美丽传说高清| 意大利孕妇电影大全在线观看| 初恋这件事国语版| 电视剧爱本无罪| www.huangse仓库电影| 武动乾坤之瑶魔乱舞| 爱情最美丽电视剧全集在线观看| 爱我几何迅雷在线观看| 电影《爱我几何》无删减完整版 | 斗罗大陆电视剧免费版| 请别相信她免费观看完整版电影| 回复术士全集免费观看完整版高清| 肮脏的交易之女人的战争| 寒战2 迅雷下载| 83版射雕英雄传| 小敏家在线电视剧免费观看全集 | 电视剧与狼共舞| 老婆招待丈夫朋友| 爱丽丝喜欢的书籍| overfloor第一季免费观看| 忍不住的继拇中字3| 武动乾坤之瑶魔乱舞| 全员加速中·对战季综艺 | 周弘《村姑》完整版 | 母亲爱上儿子的同学》电影| 太极英雄电视剧| 罪行法则韩剧免费播放| 黑暗边缘在线观看完整版免费高清| 美乃雀电影手机看| 金太郎的幸福生活电影版 | 《驯服2》丽卡和谁在一起| 图书室的女朋友在线观看完整免费版电视剧第五集 | 《初体验8》在线观看完整免费版电视| 聊斋志异三| 傻瓜猫全集| 战狼6欧式少女经典片段| 《战狼5》免费观看完整版高清| 男生女生一愁愁愁在线观看大片| 字圣传奇| 酒店1-75集一口气看完| 三生有幸遇见你免费观看西瓜网| 讲的笔顺| 青春警事| 憎侣之夜| 性影院| 中国驻英领馆遭冲闯| 剃须然后捡到女高中生| 蒲松龄粤语| 安吉拉怀特在线观看免费高清电视剧| 鱼夫荒野史免费观看完整版| 废世界电影| 精灵梦叶罗丽第四季| 《女生宿舍》2免费观看| 《爱我几何》正版| 满仓进城免费观看全集完整版| 丈夫的陷阱| 小爸爸全集在线观看| 大笑喜剧人| 台湾版《棘手狂情》香港电影 | 封神榜之爱子情深| 宁海县| 农场保卫战1| 箭在弦上免费观看全集| 星际少年队| 青蛇免费| 麦乐迪女超人在线观看完整免费高清原声满天星百 | 斗罗大陆动漫在线观看免费| 强心脏100209| 局长从后面握住我的奶| 爱我几何电影在线观看免费完整版 在线播放 | 血腥茱莉亚| 欲海情魔无删减完整版在线播放 | 《种马3》电影免费观看| 理想照耀中国 电视剧| 上位2电影| 落魄贵族琉璃川在线观看动漫免费 | 下水道的美人鱼百度影音| 法国《足球宝贝2》免费高清在线播放| 亲爱的自己电视剧免费看| 高压监狱免费观看完整版全集| 汽车| 厨神王妃:挑食王爷被征服全集免费| 汪汪队立大功第2季| 杯弓蛇影| 贝乐虎儿歌免费播放全集| 《阿姨住洒店动漫在线观看| 新西游降魔篇完整版| 铁血尖刀| 金瓶梅电视剧全集电视剧在线看免费观看| 时间之子| 九宫奇局在线观看| 心锁百度影音| 美国伦理片想要爸爸的种子在线看| 海棠红电影完整版免费观看| 机动战士高达水星的魔女| 完全饲育之爱的40天| 萨迪1980满天星在线看| 楼上老阿姨叫我修电灯在线观看| 陆战之王电视剧免费观看| 囧的呼唤| 梦幻西游五庄观副本| 木下檩檩子电影免费观看中| 女儿需要播种美国| 陆小凤全集| 吐槽西游记后传| 吞噬星空47集免费观看完整版| 部长出差的日子免费观看| 黑白配版普通话| 井底之蛙免费| 爱情填满空白第二季完整版| 乡村爱情圆舞曲39| 张警官| 《安娜与父亲》麦乐迪| 整容室第七季| 正在播放: 解决学生的性爱烦恼不穿内衣裤的美波老师硬硬教学 _美波汐里 - 91n | 世仇爱恨:最终和解全集免费| 黑暗森林满天星版法国| 保罗一家1-4在线观看| 贞观之治演员表全部介绍| 淄博电视台| 变形金刚2主演| 通城县| 私人航空2完整版在线| 电视剧少年嘉庆| 聚会的目的百度云| 喜羊羊和灰太狼之决战次时代| 戒烟不戒酒 下载| 天美激情影院| 白色城堡电视剧在线观看免| 《疯狂医生》在线观看高清| 追龙 粤语| 罗曼史在线观看| 《饥饿的女儿国》完整版| 极寒潜袭电影| 死神来了3的d9版| 法政先锋第三部粤语| 少年张君宝| 《卢旺达的玫瑰》完整版| 金银悔1~5集免费观看国语高清| 一点就到家电影| 火口山的两个人| 我独自升级动漫第二季| 大江大河2免费全集观看| 《美容院特殊待遇》电影| 好女孩电影| 金子轻松出来吧下载| 婆婆来了26| 电影默杀免费看| 日本空姐2019年上映时间| 办公室的秘书2| 恶作剧二吻| 大夏龙帝短剧免费观看| 墨西哥《瓜达卢佩玫瑰》| 画皮之真爱无悔片花| 金瓶梅金瓶| 《隐形帽子》电影完整版| 新闻女郎下载| 纯情罗曼史第一季02| 乡村爱情小夜曲| 韩剧我的妈妈| 空蝉之森手机免费观看| 好妈妈韩国免费观看完整版| 僵尸福星仔下载| 年轻时候| 《钱的味道》李恩美演的谁| 在夫面前被强行侵犯的人妻| 趣怪守护仙| 台湾版,小凤新婚| 《杉杉来了》免费观看| 恋爱先生免费观看全集| 花月佳期| 电影《急诊护士》完整版| 《食人族割奶2》电影| 幸存者1937电影免费播放| 村上沙兽皇电影免费观看高清版下载 | 阿庆讲故事| 示范销售避孕套2剧情| 爱我几何电影莫妮卡| 探险旅行| xl司令第一季全集免费观看在线播放| 心动的信号7全集免费观看| 妹汁全集在线观看国语| 麦乐迪马克思女超人在线观看完整免费高清原声满天星百 | 加勒比海盗4电影| 黄子华栋笃笑2018| 成全动漫全集免费看| 黑白配在线观看中文版| 感官世界电影| 珍馐记电视剧免费版在线观看| 哈尔滨夜店| 厦门夜生活网| 法国空乘5免费高清原声满天星| 安姨在线观看全集| 神笔马亮在线观看喜剧| 棋魂 电视剧 在线观看| 海员记录在杜苏芮影响下航行遭遇 | 法国空乘5完整版观看| 被合租刑警的粗汉肉H高NP | 为什么全世界女人都留长发| 离婚前规则主题曲| 女版战狼6免费观看高清下载| 《急诊护士》电影在线免费观看| 电影月朦胧鸟朦胧| 六年级小学生差差差| 荥经县| 夫人的侄子意大利| 死亡账号电视剧| 臣本布衣短剧全集| 电视剧欢颜| 蛇姬恋免费观看完整版| 只是结婚的关系电视剧免费观看| 我的爱宥丽| 朱丹回应叫错人名| 意大利版女版斯巴达2| 《租借女友》第一季| 余生请多指教西瓜免费看| 姐妹反目全集免费| 风月宝鉴之云雨之欢在线观看| 奇妙发型屋免费完整版| 不要忘记我爱你电影免费观看| 山医命相卜| 阿基拉和拼字比赛| 年的继拇4| 需要爸爸播种 播放| 捷克街头100集完整在线播放| 家常菜电视剧全集在线观看| 变形计2017| 一起愁愁愁电视剧全集播放| 肖申克的救赎bt种子 | 好日子高清在线观看免费播放| 白峰电影高清无广告看| 云水怒电视剧全集| 你好 李焕英 在线播放| 秘制牛杂配方| 大同县| 花蝴蝶4电视剧在线播放免费观看| 幸福最晴天女主角| 毛尖的好处| 《水浒传》在线播放| 双女任务免费观看完整版全集| 需要爸爸来播种免费观看| 卡波特百度影音| 木下之影| 布兰迪 罗伯斯| 木下零零子电影网| 离山野人之谜| 女状元文武:双全惊天下短剧全集| 画皮2电视剧全集| 花木兰 高清| 凌云壮志满天星法国版| 妖精的尾巴 oad| 爱情心心相印电视剧免费观看| 鼠来宝3电影完整版| 公之浮之6| 销售的销售秘密3hd中字| 金刚葫芦娃动漫| 爱 死亡和机器人| 伦敦奥运会男篮决赛录像| 秘密女搜查官在线观看免费全集高清| 干妈在线| 聊斋志异之连琐| 戏台电影陈佩斯抢先版免费看| 追爱家族免费全集在线观看高清| melody女超人| 满天星超人女超人免费观看| 新华社直播九三阅兵| 九尾狐传说| 顶楼的大象| 性的暴行北越未删减版| 盗墓笔记 谜海归巢| 白蛇传说之天乩| 《可疑诊疗室:特殊待遇》8| 燃烧2019电影免费观看完整版| 私密按摩师电影免费完整版| 迈克尔 道格拉斯| 美容室的待遇6免费观看| 火影忍者剧场版 忍者之路| 扫黑风暴28全集免费播放| 按摩胸部伦理片| 如意芳霏40集全电视剧| 末路电视剧| 电视剧恋人| 男按摩师做乳房按摩电影| 维修水电工的艳遇韩国电影| 京城大状师| 苏炳添说对不起大家| 特殊使命小分队| 年轻的小痍子3免费观看| 上锁的房间在线观看免费高清| 偏偏喜欢你电视剧免费观看| 电影摩登保镖| 电影美人鱼传说| 斗罗大陆免费完整观看197| 帕克电影免费观看在线中文版| 性解命| 双胞胎男主共享一女主小说宠文| 小时代3:刺金时代| 杀死比尔1完整版电影| 人民的名义 dvd| 《夫人的嘴唇》| 《圣特罗佩斯姑娘们》| 小团圆电视剧| 加勒比女海盗成版人2在线| 国产大爆乳大爆乳在线播放| 酒店1-100集全集| 二战黑豹电影免费观看高清完整版 | 庆阳市| 我和厄尔以及将死的女孩| 美国电影免费观看平台| 王爷追妻忙:王妃要和离全集免费|