Android HWASAN使用與實現原理

一、背景

為了提前檢測出Android User Sapce的app或native進程的內存錯誤問題,幫助研發定位與分析這些問題,基于Android 14版本上對HWASAN做了調研分析。

二、ASAN介紹

HWASAN是在ASAN的基礎上做了拓展,因此在介紹HWASAN之前先了解下ASAN.

ASAN(AddressSanitizer)和HWASAN(Hardware-assisted AddressSanitizer)都是內存錯誤檢測工具,用于幫助開發者發現和修復內存相關的bug,如heap-buffer-overflow、Heap-use-after-free、stack-buffer-overflow、global-buffer-overflow、double-free、Use-after-return、Alloc-dealloc-mismatch、use-after-poision等內存錯誤問題。它們的主要區別在于實現方式和性能開銷。

2.1 shadow memory

shadow memory區域來記錄實際內存的狀態信息,malloc申請的內存或其它方式申請的內存一般8字節對齊,8字節的正常內存對應1個字節的shadow memory,8個字節中可劃分為可尋址(訪問)與不可尋址區域。如,前4個字節可尋址,后4個字節不可尋址,shadow memory記錄的數據為5,即0000 0100.

normal mem與shadow mem對應關系:

shadow memory address = (normal memory address >> 3) + 0x1000000000

8字節組成的normal memory region共有3種狀態:

1)1~7個字節可尋址,即shadow memory的值為1~7。

2)8個字節都可尋址,即shadow memory的值為0。

3)0個字節可尋址,shadow memory的值為負數。

0個字節可尋址其實可以分為多種情況,如:

這塊區域是heap redzones、stack redzones、global redzones、freed memory,不同錯誤類型對應的shadow memory值也不一樣。

 Addressable:           00Partially addressable: 01 02 03 04 05 06 07 Heap left redzone:     fa (實際上Heap right redzone也是fa)Freed Heap region:     fdStack left redzone:    f1Stack mid redzone:     f2Stack right redzone:   f3Stack after return:    f5Stack use after scope: f8Global redzone:        f9Global init order:     f6Poisoned by user:      f7Container overflow:    fcArray cookie:          acIntra object redzone:  bbASan internal:         feLeft alloca redzone:   caRight alloca redzone:  cbShadow gap:            cc

每次訪問normal memory地址時,都會去結合對應的shadow mem的值檢測是否合法。

2.2 ASAN實現原理

ASAN實現原理:通過在內存分配時插入額外的代碼來檢查內存訪問是否合法。使用一個影子內存(shadow memory)區域來記錄實際內存的使用情況,當檢測到非法內存訪問時,ASAN會報告錯誤。

檢測算法:

ShadowAddr = (Addr >> 3) + Offset;
k = *ShadowAddr;
if (k != 0 && ((Addr & 7) + AccessSize > k))ReportAndCrash(Addr);

k!=0,說明Normal memory region中的8個字節并不是都可以被尋址的。

Addr & 7,將得知此次內存訪問是從memory region的第幾個byte開始的。

AccessSize是此次內存訪問需要訪問的字節長度。

(Addr&7)+AccessSize > k,則說明此次內存訪問將會訪問到不可尋址的字節。

當此次內存訪問可能會訪問到不可尋址的字節時,ASAN會報錯并結合shadow memory中具體的值明確錯誤類型。

下面以use-after-free、heap-buffer-overflow來分析具體的檢測原理。

2.2.1 use-after-free檢測

檢測原理:

1)已經free的normal memory對應的shadow memory值為0xfd.

2)已經free的normal memory區域需要放入隔離區一段時間(過段時間才允許被重新分配),防止發生錯誤時該區域已經通過malloc重新分配給其他人使用。一旦分配給其他人使用,則可能漏掉UseAfterFree的錯誤。

3)如果再次訪問該normal memory區域時,發現對應的shadow memory值為0xfd,則觸發ASAN異常報錯。

2.2.2 heap-buffer-overflow檢測

檢測原理:

1)分配內存時normal memory的前后需要插入一定長度的安全區(大小不定),且此安全區對應的shadow memory被標記為0xfa.

2)當訪問越界時,剛好訪問了normal memory的前后安全區,此安全區對應的shadow memory值為0xfa,則觸發ASAN異常報錯。

2.3 ASAN缺陷

2.3.1 存在漏檢的風險

1)use-after-free檢測依賴隔離區,一段時間后這塊內存被其他模塊重新分配后,該模塊再去訪問,則無法檢測出use-after-ree的錯誤。


2)heap-buffer-overflow檢測依賴安全區,安全區有大小限制。可能是8bytes,64bytes或者其他什么值,但不管怎么樣終歸是有限的。如果某次踩踏跨過了安全區,踩踏到另一片可尋址的內存區域,則無法檢測出heap-buffer-overflow的錯誤。

2.3.2 性能開銷大

有兩個原因導致ASAN性能開銷:

1)增加額外的內存消耗:8字節的normal memory對應1個字節的shadow memory,相當于額外多出1/8的內存用于記錄正常內存的狀態信息;內存分配時需要在前后插入安全區,用于檢測越界訪問。這兩種情況都會導致內存增加。

2)效率降低:需要在每次內存訪問時進行檢查,降低了效率;被釋放的內存,需被隔離一段時間,無法立即被重新分配,系統內存緊張時,可能存在較大的性能影響

因此,針對ASAN的存在漏檢的風險和性能開銷大的缺陷,google提出了HWASAN來改善這兩大缺陷。HWASAN解決措施:

1)措施1:64位的機器,實際上ARMv8尋址只用到了低48位,因此malloc時,HWASAN利用高8位標記tag,對應的shadow memory的值也記做tag

由于HWASAN 16字節的normal memory對應1個字節的shadow memory(ASAN為8:1),降低額外內存的消耗;由于HWASAN use-after-free檢測不依賴隔離區,解決use-after-free漏檢的風險(詳細參考3.1.1)。

2)措施2:去除ASAN安全區的內存機制

由于去除ASAN安全區的內存機制,被釋放的內存可以被其他模塊立即分配,從而提高了內存的利用效率;

同時可以解決heap-buffer-overflow漏檢的風險(詳細參考3.1.2)。

三、HWASAN介紹

HWASAN是ASAN的升級版,優化了ASAN性能開銷和漏檢風險的缺陷。

3.1 實現原理

實現原理:64位的機器,實際上ARMv8尋址只用到了低48位。HWASAN用這8bit來存儲一塊內存區域的標簽(tag)。

堆內存通過malloc分配出來,HWASAN在它返回地址時會更改該有效地址的高8位,隨機生成一個tag數值,并將該tag同步到內存對應的shadow memory,當內存釋放時,更新shadow memory的tag,HWASAN中normal memory和shadow memory的映射關系是16:1,而ASAN中二者的映射關系是8:1。通過對比內存高8位的tag與shadow memory的tag是否一致,如果不一致,會觸發HWASAN相關的內存錯誤。

下面以use-after-free、heap-buffer-overflow來分析具體的檢測原理。

3.1.1 use-after-free檢測

檢測原理:

1)分配一塊內存時,內存的高8位打上tag,對應的shadow memory的值也為該tag

2)內存釋放時,更新對應的shadow memory的tag,使這塊內存的高8位的tag與shadow memory的tag不一致

3)當再次訪問這塊內存時,發現內存的高8位的tag與shadow memory的tag不一致,觸發HWASAN內存錯誤

如,char* p =new char[10],分配10個字節的內存,由于8個字節對齊,共占用16個字節,高8位隨機生成tag1。

當內存釋放時,對應的shadow memory的值由原來的tag1更新位tag2.再次訪問p[0]時,檢查高8位tag1與shadow memory中的值tag2不一致,觸發HWASAN use-after-free.

char* p =new char[10];
delete [] p;
p[0] = "abc";

3.1.2 heap-buffer-overflow檢測

檢測原理:

1)相鄰內存的shadow memory的tag不一致

2)當訪問這塊內存地址時,會去檢測該地址高8位的tag與對應shadow memory的tag是否一直不一致。如果不一致,說明越界訪問

如,char* p =new char[10],分配10個字節的內存,由于8個字節對齊,共占用16個字節,高8位隨機生成tag2。當訪問p[16]時,由于p+16所處地址對應的shadow memory的值為tag3與p地址對應的高8位tag2不一致,會觸發HWASAN heap-buffer-overflow.

char* p =new char[10];
p[16] = "abc";

由于每次malloc,高8位的tag隨機生成,因此存在相鄰內存高8位的tag一致的概率(如tag2等于tag3),概率為1/256,在這種情況下即使越界訪問,也無法檢測出heap-buffer-overflow的問題。

3.2 HWASAN優缺點

優點:

解決了ASAN的缺陷

缺點:

1)由于采用了高8位的tag檢測機制,因此只能適用于64位的機器

2)HWASAN中normal memory和shadow memory的映射關系是16:1,即會多消耗1/16的額外內存用于記錄normal memory的狀態(tag)信息

3)每次內存分配、釋放、訪問,都需要額外的檢測工作,降低性能

4.1 系統全功能打開

1)編譯帶HWASAN的鏡像和帶hwasan的libc.so & libclang_rt.hwasan-aarch64-android.so

source build/envsetup.sh
lunch missi_auto_native_only64-userdebug
export SANITIZE_TARGET=hwaddress
make -j8 或make systemimage

libc.so路徑:

out/target/product/missi/system/lib64/bootstrap/hwasan/libc.so

libclang_rt.hwasan-aarch64-android.so路徑:out/target/product/missi/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so

2)刷機或push libc.so和libclang_rt.hwasan-aarch64-android.so到/system/lib64目錄后重啟設備

4.2 單個應用或進程打開

AndroidManifest.xml中 <application> 元素中配置了 android:debuggable="true"

<application android:debuggable="true"></application>

native進程開啟HWASAN,需要在Android.bp中做配置:

sanitize: {hwaddress: true,
},

五、Debug案例

在設備驗證HWASAN功能:

1)設置HWASAN環境變量,編譯出帶HWASAN的鏡像或libc.so + libclang_rt.hwasan-aarch64-android.so

source build/envsetup.sh
lunch missi_auto_native_only64-userdebug
export SANITIZE_TARGET=hwaddress
make -j8 或make systemimage

帶hwasan的libc.so路徑:

out/target/product/missi/system/lib64/bootstrap/hwasan/libc.so

libclang_rt.hwasan-aarch64-android.so路徑:out/target/product/missi/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so

(刷機方式效率較低,可以直接push so庫到設備)

2)push libc.so和libclang_rt.hwasan-aarch64-android.so到/system/lib64目錄后重啟設備

3)自己編寫一個Demo,push hw-asan-test-bin Demo到/system/bin目錄并執行

檢測double-free、use-after-free、invalid-free、heap-over-flow等場景,

分別執行./system/bin/hw-asan-test-bin double-free、./system/bin/hw-asan-test-bin use-after-free、./system/bin/hw-asan-test-bin heap-over-flow命令。

Demo的部分代碼:

void doubleFree() {// 分配4個字節int *ptr = (int*)malloc(4);std::cout << "ptr = " << ptr << std::endl;free(ptr);free(ptr);
}void invalidFree() {int *ptr = (int*)malloc(4);std::cout << "ptr = " << ptr << std::endl;free(ptr+1);std::cout << "invalid-free ~" << std::endl;
}void useAfterFree() {char* ptr = new char[20];std::cout << "ptr = " << ptr << std::endl;delete[] ptr;ptr[0] = 'A';std::cout << "useAfterFree ~" << std::endl;
}void heapOverFlow() {char* ptr = new char[20];std::cout << "ptr = " << ptr << std::endl;ptr[32] = 'A';std::cout << "heapOverFlow ~" << std::endl;
}void memLeak() {for (int i = 0; i < 1000; i++) {char *buffer = (char *)malloc(100);}std::cout << "memLeak ~" << std::endl;
}

4)查詢生成的tombstone文件

以下是hw-asan-test-bin Demo crash生成的HWASAN tombstone文件,如下:

Cmdline: ./system/bin/hw-asan-test-bin double-free
pid: 12968, tid: 12968, name: hw-asan-test-bi  >>> ./system/bin/hw-asan-test-bin <<<
uid: 0
tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE)
pac_enabled_keys: 000000000000000f (PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY)
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
// 內存被釋放后,0x003c95840020地址對應的內存被標記為6c
Abort message: '==12968==ERROR: HWAddressSanitizer: invalid-free on address 0x003c95840020 at pc 0x007d0dd81ba4 on thread T0
tags: 77/6c (ptr/mem)#0 0x7d0dd81ba4  (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0x23ba4) (BuildId: 558b5c131872716737ddc0a62f3382dd3df70b9a)#1 0x5b9584c230  (/system/bin/hw-asan-test-bin+0x1230) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)#2 0x5b9584c6a4  (/system/bin/hw-asan-test-bin+0x16a4) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)#3 0x7d0aab6b60  (/apex/com.android.runtime/lib64/bionic/hwasan/libc.so+0xb0b60) (BuildId: 86a860a589207e712675d7d611b13147)#4 0x5b9584c054  (/system/bin/hw-asan-test-bin+0x1054) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)[0x003c95840020,0x003c95840040) is a small unallocated heap chunk; size: 32 offset: 0Cause: use-after-free
// 分配的內存地址0x003c95840020至0x003c95840024,剛好是4個字節與Demo代碼一致
0x003c95840020 is located 0 bytes inside a 4-byte region [0x003c95840020,0x003c95840024)
// HWASAN內存釋放的堆棧信息
freed by thread T0 here:#0 0x7d0dd81ba4  (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0x23ba4) (BuildId: 558b5c131872716737ddc0a62f3382dd3df70b9a)#1 0x5b9584c188  (/system/bin/hw-asan-test-bin+0x1188) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)#2 0x5b9584c6a4  (/system/bin/hw-asan-test-bin+0x16a4) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)#3 0x7d0aab6b60  (/apex/com.android.runtime/lib64/bionic/hwasan/libc.so+0xb0b60) (BuildId: 86a860a589207e712675d7d611b13147)#4 0x5b9584c054  (/system/bin/hw-asan-test-bin+0x1054) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)
// HWASAN內存分配的堆棧信息
previously allocated here:#0 0x7d0dd82244  (/system/lib64/libclang_rt.hwasan-aarch64-android.so+0x24244) (BuildId: 558b5c131872716737ddc0a62f3382dd3df70b9a)#1 0x7d0aa671dc  (/apex/com.android.runtime/lib64/bionic/hwasan/libc.so+0x611dc) (BuildId: 86a860a589207e712675d7d611b13147)#2 0x5b9584c0d4  (/system/bin/hw-asan-test-bin+0x10d4) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)#3 0x5b9584c6a4  (/system/bin/hw-asan-test-bin+0x16a4) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)#4 0x7d0aab6b60  (/apex/com.android.runtime/lib64/bionic/hwasan/libc.so+0xb0b60) (BuildId: 86a860a589207e712675d7d611b13147)#5 0x5b9584c054  (/system/bin/hw-asan-test-bin+0x1054) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)hwasan_dev_note_heap_rb_distance: 1 1023
hwasan_dev_note_num_matching_addrs: 0
hwasan_dev_note_num_matching_addrs_4b: 0
Thread: T0 0x007400002000 stack: [0x007fc95fb000,0x007fc9dfb000) sz: 8388608 tls: [0x007d0ea6efc0,0x007d0ea72000)
Memory tags around the buggy address (one tag corresponds to 16 bytes):0x003c9583f800: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c9583f900: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c9583fa00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c9583fb00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c9583fc00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c9583fd00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c9583fe00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c9583ff00: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
=>0x003c95840000: 08  00 [6c] 00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c95840100: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c95840200: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c95840300: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c95840400: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c95840500: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c95840600: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c95840700: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 0x003c95840800: 00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00 
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):0x003c9583ff00: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. 
=>0x003c95840000: 6e  .. [..] ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. 0x003c95840100: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. ......backtrace:#00 pc 00000000000bab8c  /apex/com.android.runtime/lib64/bionic/hwasan/libc.so (abort+308) (BuildId: 86a860a589207e712675d7d611b13147)#01 pc 00000000000354b4  /system/lib64/libclang_rt.hwasan-aarch64-android.so (__sanitizer::Abort()+60) (BuildId: 558b5c131872716737ddc0a62f3382dd3df70b9a)#02 pc 0000000000033d3c  /system/lib64/libclang_rt.hwasan-aarch64-android.so (__sanitizer::Die()+204) (BuildId: 558b5c131872716737ddc0a62f3382dd3df70b9a)#03 pc 00000000000286c4  /system/lib64/libclang_rt.hwasan-aarch64-android.so (__hwasan::ScopedReport::~ScopedReport()+544) (BuildId: 558b5c131872716737ddc0a62f3382dd3df70b9a)#04 pc 0000000000027458  /system/lib64/libclang_rt.hwasan-aarch64-android.so (__hwasan::ReportInvalidFree(__sanitizer::StackTrace*, unsigned long)+560) (BuildId: 558b5c131872716737ddc0a62f3382dd3df70b9a)#05 pc 0000000000023c00  /system/lib64/libclang_rt.hwasan-aarch64-android.so (__sanitizer_free+264) (BuildId: 558b5c131872716737ddc0a62f3382dd3df70b9a)#06 pc 0000000000001230  /system/bin/hw-asan-test-bin (doubleFree()+472) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)#07 pc 00000000000016a4  /system/bin/hw-asan-test-bin (main+648) (BuildId: b3d99e0748a4c4a2607c8c2b9b91815e)#08 pc 00000000000b0b60  /apex/com.android.runtime/lib64/bionic/hwasan/libc.so (__libc_init+148) (BuildId: 86a860a589207e712675d7d611b13147)......

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

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

相關文章

ES8.13.0 java client請求響應報錯status: 200, [es/search] Failed to decode response

最近在做商城項目使用ES8.13.0做商品復雜的檢索功能時&#xff0c;遇到一個報錯如下&#xff1a; 2024-07-05 10:47:53.994 ERROR 10708 --- [nio-7500-exec-1] com.tfq.exception.RRExceptionHandler : co.elastic.clients.transport.TransportException: node: http://1…

WBCE CMS v1.5.2 遠程命令執行漏洞(CVE-2022-25099)

前言 CVE-2022-25099 是一個影響 WBCE CMS v1.5.2 的嚴重安全漏洞&#xff0c;具體存在于 /languages/index.php 組件中。該漏洞允許攻擊者通過上傳精心構造的 PHP 文件在受影響的系統上執行任意代碼。 技術細節 受影響組件&#xff1a;/languages/index.php受影響版本&…

如何在 Odoo 16 中向新視圖添加字段

例如,讓我們看看如何在新視圖或新操作窗口中創建“many2one”字段。 請考慮下面的屏幕截圖,它表示不包含任何字段的新視圖類型或客戶端操作窗口。 我們現在可以將與“res.partner”關聯的“多對一”字段引入到我們的新視圖或客戶端操作窗口中。 為了實現這一點,在 XML 模板…

ShardingSphere

ShardingSphere 是一個開源的分布式數據庫中間件生態系統&#xff0c;由 Apache 基金會孵化和維護。它的主要目標是幫助開發者解決分庫分表、分布式事務和數據加密等分布式數據庫應用中的常見問題。ShardingSphere 提供了多種組件&#xff0c;如 Sharding-JDBC、Sharding-Proxy…

Using a text embedding model locally with semantic kernel

題意&#xff1a;在本地使用帶有語義核&#xff08;Semantic Kernel&#xff09;的文本嵌入模型 問題背景&#xff1a; Ive been reading Stephen Toubs blog post about building a simple console-based .NET chat application from the ground up with semantic-kernel. Im…

idea中maven全局配置

配置了就不需要每次創建項目都來設置maven倉庫了。 1.先把項目全關了 2. 進入全局設置 3.設置maven的倉庫就可以了

SpringBoot實現多數據源切換

1. 概述 隨著項目規模的擴大和業務需求的復雜化&#xff0c;單一數據源已經不能滿足實際開發中的需求。在許多情況下&#xff0c;我們需要同時操作多個數據庫&#xff0c;或者需要將不同類型的數據存儲在不同的數據庫中。這時&#xff0c;多數據源場景成為必不可少的解決方案。…

【CentOS7.6】docker部署EMQX教程,本地鏡像直接導入(附下載鏈接),沒法在云服務器上魔法拉取鏡像的快來

總覽 先把下載鏈接放在這里吧&#xff0c;這是 EMQX 的 tar 包&#xff0c;能夠直接導入 CentOS 的 docker&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1rSGSLoVvj83ai6d5oolg8Q?pwd0108 提取碼&#xff1a;0108 一、安裝配置教程 1.將 EMQX-latest.tar 包導入…

服務器重裝系統時數據丟失?有哪些方法可以避免

為了避免在服務器重裝系統時數據丟失&#xff0c;可以采取以下預防措施&#xff1a; 1. 數據備份&#xff1a;在重裝系統之前&#xff0c;備份所有重要的數據和配置文件。備份可以通過以下方式進行&#xff1a; - 使用外部存儲設備(如USB硬盤、NAS等)進行備份。 - 利用備份軟件…

學習成績總是上不去?中學生把握好這5個環節,助你提高成績

在中學時代&#xff0c;考試我們并不陌生。每隔一段時間&#xff0c;學校就會安排我們參加考試。學生時代&#xff0c;我們參加的考試有很多。對于中學生來說&#xff0c;考試成績是我們一直關心的事情。很多學生非常努力的學習&#xff0c;成績卻上不去。這是非常可惜的&#…

[圖解]企業應用架構模式2024新譯本講解19-數據映射器1

1 00:00:01,720 --> 00:00:03,950 下一個我們要講的就是 2 00:00:04,660 --> 00:00:07,420 數據映射器這個模式 3 00:00:09,760 --> 00:00:13,420 這個也是在數據源模式里面 4 00:00:13,430 --> 00:00:14,820 用得最廣泛的 5 00:00:16,250 --> 00:00:19,170…

【軟件工程中的噴泉模型及其優缺點】

文章目錄 一、噴泉模型是什么&#xff1f;二、噴泉模型的優點1. 靈活性和適應性2. 迭代開發3. 風險控制 三、噴泉模型的缺點1. 需求不明確性2. 可能造成資源浪費3. 需要良好的溝通與協作 一、噴泉模型是什么&#xff1f; 噴泉模型是一種迭代增量開發模型&#xff0c;其核心理念…

鏈篦機回轉窯球團生產工藝

生球在回轉窯氧化焙燒&#xff0c;回轉窯頭部設有燃燒器&#xff0c;燃料可以采用氣體、固體、液體。 來自環冷機一冷卻段的高溫廢氣作為二次風進入窯內參與燃燒&#xff0c;燒成成品球進入環冷機。 環冷機采用鼓風冷卻&#xff0c;熱風風箱分為四段&#xff1a; 一段氣體引至…

無人機有哪些關鍵技術?

一、控制技術 無人機的核心還是在控制上&#xff0c;飛控系統的可靠性、穩定性及可擴展性是其中重要的指標。可靠性上&#xff0c;除了器件選型之外&#xff0c;目前主要靠多余度來增加&#xff1b;穩定性主要體現在多場景下仍能保持良好的工作狀態&#xff0c;主要靠算法來進…

QML-各類布局

Colunm布局 Column{id:colspacing: 30Repeater{id:repmodel: ListModel{}Button{width: 100height: 50text: "btn"index}}//開始時候移動move: Transition {NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce }}//添加時變化add:Transi…

【Nginx】docker運行Nginx及配置

Nginx鏡像的獲取 直接從Docker Hub拉取Nginx鏡像通過Dockerfile構建Nginx鏡像后拉取 二者區別 主要區別在于定制化程度和構建過程的控制&#xff1a; 直接拉取Nginx鏡像&#xff1a; 簡便性&#xff1a;直接使用docker pull nginx命令可以快速拉取官方的Nginx鏡像。這個過程…

通透!手把教你如何從頭構建一個機器學習模型

目錄 1.業務理解 2.數據收集和準備 數據采集 探索性數據分析 (EDA) 和數據清理 特征選擇 3.建立機器學習模型 選擇正確的模型 分割數據 訓練模型 模型評估 4.模型優化 5.部署模型 今天我將帶領大家一步步的來構建一個機器學習模型。 我們將按照以下步驟開發客戶流失…

賽博解壓板

目錄 開頭程序程序的流程圖程序的解壓效果(暫無&#xff0c;但可以運行一下上面的代碼)結尾 開頭 大家好&#xff0c;我叫這是我58。今天&#xff0c;我們要看關于賽博解壓板的一些東西。 程序 #define _CRT_SECURE_NO_WARNINGS 1 #define ROW 6//ROW表示行數&#xff0c;可…

【ARM 常見匯編指令學習 7.1 -- LDRH 半字讀取指令】

請閱讀【嵌入式開發學習必備專欄】 文章目錄 LDRH 使用介紹LDRH&#xff08;Load Register Half-word&#xff09;總結 LDRH 使用介紹 在ARMv9架構中&#xff0c;匯編指令LDRH用于從內存中載入數據到寄存器的指令&#xff0c;下面將分別對它進行詳細介紹&#xff1a; LDRH&am…

【基礎算法】UE中實現輪播

本期作者&#xff1a;尼克 易知微3D引擎技術負責人 當前N 總數M 從0到M-1 從1到M 感謝閱讀&#xff0c;以上內容均由易知微3D引擎團隊原創設計&#xff0c;以及易知微版權所有&#xff0c;轉載請注明出處&#xff0c;違者必究&#xff0c;謝謝您的合作。申請轉載授權后臺回復【…