91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一次Rust重寫基礎軟件的實踐

jf_wN0SrCdH ? 來源:Rust語言中文社區(qū) ? 2024-01-25 11:21 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

受到2022年“谷歌使用Rust重寫Android系統(tǒng)且所有Rust代碼的內(nèi)存安全漏洞為零” [1] 的啟發(fā),最近筆者懷著濃厚的興趣也順應Rust 的潮流,嘗試著將一款C語言開發(fā)的基礎軟件轉(zhuǎn)化為 Rust 語言。本文的主要目的是通過記錄此次轉(zhuǎn)化過程中遇到的比較常見且有意思的問題以及解決此問題的方法與大家一起做相關(guān)的技術(shù)交流和討論。

問題描述

本文將記錄轉(zhuǎn)化過程中遇到的另外一個問題。該問題是由已經(jīng)轉(zhuǎn)化完成的 Rust 代碼使用到軟件中引入的第三方軟件包和鏈接庫所導致的。設想這樣一個場景:Rust 項目中完成某一個功能點需要用到一個或多個第三方軟件包和鏈接庫。這顯然是很常見的用戶場景,但是由于用戶環(huán)境不同,用戶安裝的第三方軟件包和鏈接庫的版本不同,使得轉(zhuǎn)化后的 Rust 代碼必須要做適當?shù)募嫒萏幚怼?/p>

這里所說的用戶的環(huán)境不同,可以理解為芯片指令集的平臺不同,如 Intel x86 以及國產(chǎn)的 ARM 麒麟服務器。當然更常見的情形是芯片平臺相同,但是存在操作系統(tǒng)層面第三方軟件包和鏈接庫安裝的差異,如 x86 下的 Ubuntu 和 CentOS 中用戶安裝了不同版本的第三方軟件包和鏈接庫等。

事實上,即使排除所有平臺和系統(tǒng)層面的差異,由于用戶安裝了該基礎軟件所依賴的不同版本的第三方軟件包和鏈接庫,然而這些第三方軟件包或者鏈接庫由于自身的演進導致不同版本之間存在較大差異(可能實現(xiàn)相同功能的函數(shù)和函數(shù)簽名都有千差萬別),這給我重寫該軟件的工作帶來了一些挑戰(zhàn)?;谏鲜稣f明,在完成重寫該基礎軟件的過程中如何使得轉(zhuǎn)化后的 Rust 代碼能兼容該基礎軟件所依賴的主流第三方軟件包和鏈接庫則是我遇到的最大挑戰(zhàn)。需要說明的是這里的第三方軟件包和鏈接庫可能是基于 Rust 語言開發(fā)的,也可能是基于 C 語言開發(fā)的。

解決方案

對于此問題的解決方案需要使用 Rust FFI(Foreign Function Interface) [1],這基本上是沒有太大爭議的。因為在本次軟件重寫過程中我遇到的場景是:對于不同版本的鏈接庫使用哪個版本的函數(shù)取決于用戶的安裝運行時環(huán)境,所以除了 Rust FFI,在代碼適配上我還考慮了使用 Rust features [2] 機制。

下面我簡化了一下場景和解決方案,同時我把樣本代碼放到了我的 github [3] 里,歡迎大家一起交流。如樣本代碼所示,my-rust-bin 文件夾中的一段業(yè)務代碼需要調(diào)用到靜態(tài)鏈接庫 my_rust_lib 中的函數(shù),該鏈接庫有兩個版本 v1(在文件夾 my-rust-lib-v1 中) 和 v2(在文件夾 my-rust-lib-v2 中), 且不同版本的庫其函數(shù)不一樣。

my-rust-lib-v1 對應的業(yè)務函數(shù)為:pub fn my_rust_lib_v1(left: usize, right: usize) -> usize

my-rust-lib-v2 對應的業(yè)務函數(shù)為:pub fn my_rust_lib_v2(left: usize, right: usize) -> usize

另外一個 lib 文件夾的目的其實是為了模擬用戶本地安裝的鏈接庫??梢苑謩e編譯不同版本的靜態(tài)鏈接庫,然后把生成的庫文件(在本例中是)libmy_rust_lib.a, 然后把不同版本的庫文件拷貝到此文件夾下,以此來模擬用戶環(huán)境中安裝的不同版本的鏈接庫。解決方案中的關(guān)鍵點在于 my-rust-bin 中,

首先在 my-rust-bin 的 Cargo.toml 中有定義對應的 features,如下所示:

[features]
v1=[]
v2=[]

其次在 my-rust-bin 的 src/main.rs 下的代碼如下:

#[cfg(feature="v1")]
modbindingmylib{
extern"C"{
pubfnmy_rust_lib_v1(left:usize,right:usize)->usize;
}
}

#[cfg(feature="v2")]
modbindingmylib{
extern"C"{
pubfnmy_rust_lib_v2(left:usize,right:usize)->usize;
}
}

#[cfg(not(any(feature="v1",feature="v2")))]
compile_error!("Pleasespecifyeither'v1'or'v2'feature");

pubfnmy_rust_lib(left:usize,right:usize)->usize{
#[cfg(feature="v1")]
unsafe{
returnbindingmylib::my_rust_lib_v1(left,right);
}

#[cfg(feature="v2")]
unsafe{
returnbindingmylib::my_rust_lib_v2(left,right);
}
}

fnmain(){
letr_value:usize=my_rust_lib(3,5);
println!("Thereturnvalueofmy_rust_libis[{}]",r_value);
}

現(xiàn)在我來解讀一下這段代碼。代碼先分別定義一個相同的模塊 bindingmylib,然后根據(jù) features 分別引入的依賴,使用的不同的靜態(tài)鏈接庫函數(shù)(my_rust_lib_v1 和 my_rust_lib_v2), 同時通過 compile_error! 定義一個沒有設置 v1 和 v2 features 的編譯錯誤(防止編譯時忘記設置 features選項,下面在編譯環(huán)節(jié)的時候有用)。最后將兩個有差異的函數(shù)統(tǒng)一為函數(shù) my_rust_lib,并在該函數(shù)中根據(jù) features 定義分別調(diào)用不同的函數(shù)并返回相應的值。

最后是在 my-rust-bin 中編譯二進制文件:

編譯并運行 v1 的二進制文件

#編譯v1版本的my-rust-bin
$cdmy-rust-bin
$cargobuild--features="v1"

#運行v1版本的my-rust-bin
$target/debug/my-rust-bin
my_rust_lib_v1:8
Thereturnvalueofmy_rust_libis[8]

編譯并運行 v2 的二進制文件

#編譯v2版本的my-rust-bin
$cdmy-rust-bin
$cargobuild--features="v2"

#運行v2版本的my-rust-bin
$target/debug/my-rust-bin
my_rust_lib_v2:8
Thereturnvalueofmy_rust_libis[8]

備注:如果編譯的時候沒有設置 --features 則會有如下輸出:

$cargobuild
error:Pleasespecifyeither'v1'or'v2'feature
-->src/main.rs1
|
16|compile_error!("Pleasespecifyeither'v1'or'v2'feature");
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

至此,用戶在編譯好該基礎軟件之后,就可以無感知的通過統(tǒng)一的函數(shù)入口調(diào)用不同版本的相同鏈接庫中的不同函數(shù)了。

總結(jié)

本文主要是在簡化了問題的實際場景以后,解決不同版本的同一軟件包或者鏈接庫中,函數(shù)及其函數(shù)簽名不同導致的調(diào)用問題。之所以說簡化,主要是本文所描述的場景中,my-rust-bin 和其依賴的外部鏈接庫均是 Rust 編寫。而在我的實際場景中則會更復雜一些,存在著 Rust 代碼依賴 C 編寫的外部鏈接庫,同時存在混合的原來 C 代碼部分依賴新改寫的 Rust 外部鏈接庫的情況。但是無論哪種情況,萬變不離其宗,我們都可以從這種最簡單的場景出發(fā)去解決遇到的問題。

關(guān)于作者

張懷龍曾就職于阿爾卡特朗訊,百度,IBM等企業(yè)從事云計算研發(fā)相關(guān)的工作。目前就職于 Intel 中國,擔任云原生開發(fā)工程師并致力于云原生、服務網(wǎng)格等技術(shù)領(lǐng)域研究實踐,也是Istio 的maintainer的開發(fā)者。曾多次在 KubeCon、ServiceMeshCon、IstioCon、GOTC 和 InfoQ/QCon 等大會上發(fā)表演講。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    7402

    瀏覽量

    129342
  • C語言
    +關(guān)注

    關(guān)注

    183

    文章

    7644

    瀏覽量

    145643
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4968

    瀏覽量

    74001
  • Rust
    +關(guān)注

    關(guān)注

    1

    文章

    240

    瀏覽量

    7594

原文標題:一次Rust重寫基礎軟件的實踐(二)

文章出處:【微信號:Rust語言中文社區(qū),微信公眾號:Rust語言中文社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    Rust GUI實踐Rust-Qt模塊

    Rust-Qt 是 Rust 語言的個 Qt 綁定庫,它允許 Rust 開發(fā)者使用 Qt 框架來創(chuàng)建跨平臺的圖形界面應用程序。Qt 是
    的頭像 發(fā)表于 09-30 16:43 ?2814次閱讀

    智能客服驅(qū)動效率和體驗升級,上海電信+昇騰AI的一次民生應用實踐

    上海電信+昇騰AI的一次民生應用實踐
    的頭像 發(fā)表于 07-30 23:44 ?2955次閱讀
    智能客服驅(qū)動效率和體驗升級,上海電信+昇騰AI的<b class='flag-5'>一次</b>民生應用<b class='flag-5'>實踐</b>

    步降低冰箱旋轉(zhuǎn)式壓縮機噪聲的一次實踐

    步降低冰箱旋轉(zhuǎn)式壓縮機噪聲的一次實踐
    發(fā)表于 05-20 15:19 ?646次下載

    一次電池為什么不能被充電?

    一次電池為什么不能被充電? 一次電池不能被充電再生是構(gòu)成一次電池體系的本性所決定的,因為一次電池的電極反應不可逆,也就是說,放電后的放電產(chǎn)
    發(fā)表于 10-28 15:29 ?6196次閱讀

    循環(huán)充放電一次就是少一次壽命嗎?

    循環(huán)充放電一次就是少一次壽命嗎?     循環(huán)就是使用,我們是在使用電池,關(guān)心的是使
    發(fā)表于 11-11 13:59 ?1045次閱讀

    電池循環(huán)充放電一次就是少一次壽命嗎?

    電池循環(huán)充放電一次就是少一次壽命嗎? 循環(huán)就是使用,我們是在使用電池,關(guān)心的是使用的時間,為了衡量充電電池
    發(fā)表于 09-06 11:05 ?4013次閱讀

    微軟開發(fā)基于Rust的新編程語言,將很快開源

    使用Rust重寫各種產(chǎn)品,因為在過去的十年里,微軟70%以上的安全補丁都提供了與內(nèi)存相關(guān)的錯誤,而Rust正是解決這個問題的良藥。 而根據(jù)ZDNet的報導,近日在一次演講中,談到微軟為
    的頭像 發(fā)表于 12-03 10:36 ?4340次閱讀

    電氣一次識圖基礎

    電氣一次識圖基礎
    的頭像 發(fā)表于 11-12 11:24 ?2697次閱讀

    Cloudflare用Rust重寫Nginx C模塊,構(gòu)建沒有Nginx的未來

    近日,Cloudflare 工程師介紹了如何使用 Rust 重寫基于 C 語言的 Nginx 模塊。Cloudflare 工程師在博客寫道,他們用 Rust 為 Cloudflare 基礎設施中最
    的頭像 發(fā)表于 03-08 09:36 ?1361次閱讀

    Rust重寫的LSP:KCL IDE 插件的功能介紹與設計解析

    在這次更新中,我們發(fā)布了全新的 KCL VS Code 插件,并且用 Rust 重寫了 LSP 的 Server 端。我們提供了 IDE 中常用的代碼輔助功能,如高亮、跳轉(zhuǎn)、補全、Outline、懸停、錯誤提示等。
    的頭像 發(fā)表于 05-11 09:39 ?1913次閱讀
    <b class='flag-5'>Rust</b><b class='flag-5'>重寫</b>的LSP:KCL IDE 插件的功能介紹與設計解析

    Windows 11初嘗Rust,36000行內(nèi)核代碼已重寫!

    更早些時候,微軟用 Rust 重寫了 DirectWrite Core 庫的概念驗證,它是 Windows 的 DWrite 引擎的 Windows App SDK 實現(xiàn),用于文本分析、布局和渲染
    的頭像 發(fā)表于 05-19 16:39 ?1714次閱讀
    Windows 11初嘗<b class='flag-5'>Rust</b>,36000行內(nèi)核代碼已<b class='flag-5'>重寫</b>!

    一次調(diào)頻和二調(diào)頻的概念 一次調(diào)頻可以實現(xiàn)無差調(diào)節(jié)?

    一次調(diào)頻和二調(diào)頻的概念 一次調(diào)頻可以實現(xiàn)無差調(diào)節(jié)? 、一次調(diào)頻和二調(diào)頻的概念 1.
    的頭像 發(fā)表于 10-17 16:15 ?1.3w次閱讀

    Rust重寫基礎軟件實踐代碼

    在項目轉(zhuǎn)化過程中我遇到了個與 CAS (Compare and Swap) [2] 操作實現(xiàn)相關(guān)的問題,在計算機科學中CAS 是多線程/協(xié)程中用于實現(xiàn)同步的原子指令。
    的頭像 發(fā)表于 01-19 10:05 ?1196次閱讀

    JavaScript與Rust和WebAssembly集成

    偶然一次機會,接觸了Rust的代碼。當時想給團隊小伙伴做演示,發(fā)現(xiàn)自己并不能在移動端按照文檔生成演示demo。我就想,要是Rust代碼能轉(zhuǎn)化成JavaScript就好了。結(jié)果搜,還真
    的頭像 發(fā)表于 01-24 15:43 ?1001次閱讀
    JavaScript與<b class='flag-5'>Rust</b>和WebAssembly集成

    從內(nèi)核到生態(tài):一次看懂HarmonyOS 6如何重寫操作系統(tǒng)的“基礎代碼”

    在移動操作系統(tǒng)競爭進入“深水區(qū)”的當下,用戶對于系統(tǒng)體驗的期待早已不再局限于功能的簡單疊加,而是追求種從底層架構(gòu)革新帶來的全方位飛躍。HarmonyOS 6的正式發(fā)布,正是這樣一次對操作系統(tǒng)
    的頭像 發(fā)表于 12-31 09:09 ?269次閱讀
    從內(nèi)核到生態(tài):<b class='flag-5'>一次</b>看懂HarmonyOS 6如何<b class='flag-5'>重寫</b>操作系統(tǒng)的“基礎代碼”