前言
公司傳統的采集系統都是基於Windows開發,Windows系統因為圖形界面操作的便利性以及軟件開發的便捷性廣受各個公司所青睞,但是大多數情況我們只需要在工控機上運行一個小小的軟件反而需要安裝臃腫的Windows系統,這是得不償失的。
受限於普通工控設備的性能問題,Windows系統也經常出現藍屏和死機等情況。鑒於以上問題以及為了提高工控機的穩定性和對各個平台的兼容性支持,我們決定將軟件制作為跨平台版本。
本次開發主要是移植串口采集程序到Linux系統(Ubuntu18.04)中,基於.NetCore 2.1平台,使用C#語言。
一.安裝Ubuntu18.04
Ubuntu官網下載最新的鏡像包以及Rufus工具,准備一個U盤,打開Rufus工具,按照下圖進行配置,點擊開始制作U盤按照工具。

Rufus啟動盤配置(圖片來自網絡)
U盤插入工控機,設置BiosU盤優先啟動,進入到安裝選項時直接選擇Install Ubuntu即可,或者進入系統再安裝也可以。安裝過程按需選擇最小化安裝或者完整安裝都不影響使用,其他功能按需選擇,一直下一步等待安裝完成。
二..NetCore環境搭建
工欲善其事必先利其器。搞.NetCore開發一套穩定的開發環境必不可少,除了.NetCore的運行環境。還需要開啟SSH遠程服務,方便后期調試。
安裝.NetCore2.1
在Ubuntu的終端執行以下命令即可自動完成
| wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/ wget -q https://packages.microsoft.com/config/ubuntu/18.04/prod.list sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list sudo apt-get install apt-transport-https sudo apt-get update sudo apt-get install dotnet-sdk-2.1 //安裝.NetCore2.1的SDK包 |
開啟SSH服務
| ps -e |gerp ssh // 查看ssh服務 sudo apt-get update sudo apt-get install openssh-server // 安裝ssh服務 sudo ps -ef|grep ssh service sshd start // 開啟服務 service sshd stop // 關閉服務 |
三.將.NetCore程序編譯為跨平台版本
由於.NetCore本身就是跨平台的,所以Windows平台上一次編譯好的程序可以運行在多種包含相同版本.NetCore RunTime的環境中。編寫跨平台代碼要注意保證代碼的兼容性,適配各個操作系統的路徑以及第三方包是否支持該系統。本次移植的是一個小小的串口采集程序,主要功能就是從數據庫獲取串口參數,指令,然后使用串口下發數據,收到數據后解析存入數據庫。下面我寫下我遇見的坑。
1.Linux路徑問題
這個問題很經典,Windows路徑組成是單反斜杠’\’,但有些編譯器可能會不認’\’,所以代碼中經常使用’\\’來轉義使用。Windows目錄區分C,D盤,路徑一般是這種形式 C:\Program Files
Linux 路徑一般使用單斜杠’/’,Linux目錄類似樹形,最頂層是根目錄,路徑一般是這種形式 /home/ ProgramFiles
以讀取當前目錄的配置文件為例,建議使用Directory.GetCurrentDirectory()方法獲取當前路徑,使用Path.DirectorySeparatorChar獲取當前系統的目錄分割符,示例代碼如下:
| string strPath = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "server.xml"; |
2.使用跨平台的串口類
現在版本的.NetCore還不算太完善,一些系統自帶的包都不能很好的移植。在開發過程中串口包是我趟坑摔得最慘的。。。。。。
目前System.IO.Ports中的SerialPort包穩定版是4.5,還不支持跨平台使用。查了網上的資料大多使用SerialPortStream等第三包來進行移植,但是效果都不太理想。一方面代碼改動的地方大。另一方面,由於第三方包來源參差不齊,包的性能都不是很穩定,即便是SerialPortStream這種廣泛使用的第三方包,我在調試的過程中也出現了數據接收不完整的情況。
在看了微軟的技術文檔后,發現NuGet中已經有了System.IO.Ports SerialPort的預覽版4.6(在我寫這篇文章時已經發布了4.6的穩定版),里面集成了對.NetCore的支持。在管理NuGet程序包界面,勾選包括預覽發行版,搜索System.IO.Ports包,選擇對應的版本(4.6)直接更新就完事兒(我這里已經更新了所以按鈕是灰色的)。

管理NuGet程序包界面
經過測試,微軟官方的包還是蠻穩定的。
3.數據插入時間格式問題
解決完路徑問題和串口問題后,基本上軟件就能在Linux環境中運行了。采集過程中一直有數據返回,但是查看數據庫發現只有日期,時間都是0。無奈只有使用WriteLine大法進行調試。后來發現當使用DateTime.Now獲取時間時,Windows與Linux獲取的格式不一致
例:
window 獲取時間格式 2019/9/17 15:02:00
linux 獲取時間格式 2019/9/17 下午 15:02:00
解決方案:所有在插入數據庫時直接將日期格式化成字符串(SaveDate.ToString("yyyy-MM-dd HH:mm:ss"))即可。
4.程序的編譯與發布
.NetCore程序在Windows平台調試完成后,就可以移植到Linux上啦。發布可以使用Debug版本或Release版本。生成Debug版本的目的是用於調試,而生成Release版本的目的是用於版本的最終分發,一般還是建議使用Release方式。
Debug版本不會把需要的程序集放在當前程序的目錄中(如NuGet包一般放在個人文件夾里),如果要正常運行程序還需手動分配所有的依賴包,並在Debug的生成目錄修改配置文件中依賴包的路徑。這種方式太麻煩並且Debug版也不會針對代碼進行優化。
使用Release版會把所有的依賴包打包到當前程序目錄,並對代碼進行優化,方便分發使用。具體生成流程如下:
右鍵項目->選擇發布 配置好目標運行時,目標框架,輸出路徑等參數,點擊發布完事兒。

配置發布參數
發布成功后會在設定路徑生成文件夾存放編譯好的程序,直接將該文件夾拷到目標設備上就可以了。下面會講如何運行.NetCore程序。
四.軟件的部署
1.啟動程序
程序經過編譯后不再是Windows上常見的exe格式,而是Dll文件。無論Windows還是Linux都需要在終端界面執行指令運行(Windows和Linux指令類似)。指令如下:
| cd 主程序所在文件夾路徑 dotnet 主程序.dll |
2.注意事項
1.如果要開啟串口等操作,需要使用管理員權限運行。
2.Windows串口與Linux串口有所區別,Windows串口可以設備管理器里面查看,命名一般為“COM1”,串口號可以根據需要更改。Linux中串口可通過指令 ls /dev/ttyU*查看,命名一般為“/dev/ttyUSB0”,串口號根據設備插入的順序疊加。
3.啟動軟件如果不想展示運行的界面,可以使用nohup命令(nohup dotnet 主程序.dll &) 將程序放在后台運行,使用jobs指令可以查看當前后台的運行情況。
4.使用top命令可以查看當前系統的資源占用情況。
5.在之前的操作中我們已經開啟了SSH的遠程訪問,使用Xshell等工具可以方便地遠程連接Linux終端,執行程序的結果也會在Xshell中同步展示出來。具體使用方法這里不再贅述,有需要自行百度。
寫在最后
由於我沒有Linux使用經驗,以及跨平台開發經驗,在開發的過程中也是趟坑不少。好在現在網上相關資料多,自己摸索着也最終解決了。要想成為優秀的開發人員,我要學習的東西還很多,謹以此文記錄本次趟坑的經歷。
