精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

3天內不再提示

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

jf_wN0SrCdH ? 來源:Rust語言中文社區 ? 2024-01-25 11:21 ? 次閱讀

前言

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

問題描述

本文將記錄轉化過程中遇到的另外一個問題。該問題是由已經轉化完成的 Rust 代碼使用到軟件中引入的第三方軟件包和鏈接庫所導致的。設想這樣一個場景:Rust 項目中完成某一個功能點需要用到一個或多個第三方軟件包和鏈接庫。這顯然是很常見的用戶場景,但是由于用戶環境不同,用戶安裝的第三方軟件包和鏈接庫的版本不同,使得轉化后的 Rust 代碼必須要做適當的兼容處理。

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

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

解決方案

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

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

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

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

另外一個 lib 文件夾的目的其實是為了模擬用戶本地安裝的鏈接庫。可以分別編譯不同版本的靜態鏈接庫,然后把生成的庫文件(在本例中是)libmy_rust_lib.a, 然后把不同版本的庫文件拷貝到此文件夾下,以此來模擬用戶環境中安裝的不同版本的鏈接庫。解決方案中的關鍵點在于 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);
}

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

最后是在 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");
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

總結

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

關于作者

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

審核編輯:湯梓紅

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

    關注

    37

    文章

    6737

    瀏覽量

    123190
  • C語言
    +關注

    關注

    180

    文章

    7598

    瀏覽量

    136178
  • 代碼
    +關注

    關注

    30

    文章

    4744

    瀏覽量

    68345
  • Rust
    +關注

    關注

    1

    文章

    228

    瀏覽量

    6570

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

文章出處:【微信號:Rust語言中文社區,微信公眾號:Rust語言中文社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Rust GUI實踐Rust-Qt模塊

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

    步降低冰箱旋轉式壓縮機噪聲的一次實踐

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

    循環充放電一次就是少一次壽命嗎?

    循環充放電一次就是少一次壽命嗎?循環就是使用,我們是在使用電池,關心的是使用的時間,為了衡量充電電池的到底可以使用多長時間這樣個性能,就規定了循環
    發表于 09-07 02:06 ?2041次閱讀

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

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

    循環充放電一次就是少一次壽命嗎?

    循環充放電一次就是少一次壽命嗎?     循環就是使用,我們是在使用電池,關心的是使
    發表于 11-11 13:59 ?844次閱讀

    電池循環充放電一次就是少一次壽命嗎?

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

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

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

    微軟正在研發基于Rust新的安全編程語言

    為提高 Windows 10 的安全性,微軟研究人員 Matthew Parkinson 在本周的一次演講中披露:微軟正基于 Rust 開發新的安全編程語言。
    的頭像 發表于 12-06 16:36 ?3183次閱讀

    電氣一次識圖基礎

    電氣一次識圖基礎
    的頭像 發表于 11-12 11:24 ?2100次閱讀

    Cloudflare用Rust重寫Nginx C模塊,構建沒有Nginx的未來

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

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

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

    Windows 11初嘗Rust,36000行內核代碼已重寫

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

    一次電池與二電池介紹

    電池大致可分為“一次電池”和“二電池”。 “一次電池”是一次用完就處理掉的一次性電池, 而可以反復充電循環使用的電池稱為“二
    的頭像 發表于 07-05 17:24 ?4550次閱讀
    <b class='flag-5'>一次</b>電池與二<b class='flag-5'>次</b>電池介紹

    一次調頻和二調頻的概念 一次調頻可以實現無差調節?

    一次調頻和二調頻的概念 一次調頻可以實現無差調節? 一次調頻和二調頻的概念 1.
    的頭像 發表于 10-17 16:15 ?8941次閱讀

    Rust重寫基礎軟件實踐代碼

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