\ 跳到主要內容

發表文章

A brief introduction to ELF

繼 這篇文章 ,這篇將接續對於elf檔案的認識。ELF(Executable Linkable Format)檔的結構由多個區段組成,包括file header, .text section, .data section 以及 .bss section等區段。其中 .text存放程式碼區段,.data存放已初始化的全域變數以及靜態變數,而.bss存放已初始化的全域變數以及靜態變數。這篇的小實驗同樣是藉由main.cpp這支簡單的小程式來進行。   main.cpp #define N 81 int main(){ return 0;//this is the end } size  size這個指令可以用來查看ELF檔各個區段的長度,在main.cpp檔中,我們並未宣告任何的變數,於是可以看到以下在於.text以及.data區段的長度皆為0。 $ size main.o text data bss dec hex filename 103 0 0 103 67 main.o
最近的文章

.bashrc與環境變數設定

這一篇將用「Linux下啟動MATLAB」來認識.bashrc以及設定環境變數。  .bashrc "bash"是Bourne Again SHell的簡稱,是Linux預設使用的shell。使用者,termial,shell這三個元素的相關性可以藉由「使用者,透過terminal,與shell進行溝通」來描述。在開啟terminal時,bash就會被啟動,同時載入.bashrc裡的資訊。以下用一個小實驗來呈現這一點,實驗中在.bashrc裡頭加入: echo 'BASHRC' 然後開啟terminal,即可看見terminal在開啟時,載入了.bashrc並且執行我們在裡頭寫的,希望它印出BASHRC字樣的指令: BASHRC :~$ 我們也可以在裡面設定一些功能,比如說terminal的個人化設置或是環境變數的設定。在 python importation 中有提過「python importation 的機制在於編輯 sys.path」,與在.bashrc中設定環境變數PATH要做的事情是相似的:編輯搜索的目錄,讓系統在一或多個工作目錄底下能夠找的到特定的檔案。 加入環境變數,讓MATLAB能夠在任何目錄下被執行 在Linux下安裝好MATLAB後,只能藉由CLI啟動,且需先進到"matlab"的目錄底下: ~$ cd /usr/local/MATLAB/R2022a/bin/ /usr/local/MATLAB/R2022a/bin$ ./matlab 需進到目錄底下才能夠啟動MATLAB有損方便性,若是我們希望能在所有目錄底下啟動matlab,則可以在.bashrc中加入環境變數: PATH=$PATH:/usr/local/MATLAB/R2022a/bin 接著藉由source重新整理(重新開啟一個terminal也會去讀取更新後的.bashr進而達到同樣的目的): /$ source .bashrc 重新載入.bashrc後即可在任一目錄底下啟動matlab: ~$ matlab

A brief introduction to Object file

從 這篇 可以看到在vim中開啟main.o,而上圖充斥著1&0,看似截然不同的兩個東西。 main.o in vim ^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@ ^@^@^@^@^@^@^@^@^@^@X^B^@^@^@^@^@^@^@^@^@^ @@^@^@^@^@^@@^@^L^@^K^@ó^O^^úUH å¸^@^@^ @^@]Ã^@GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0^@^@^@^@^@^@^D^@^...... 理解兩者差異的原因,可以從兩個面向去釐清: 1. 所有的檔案都是由0&1組成的 電腦中的檔案皆是藉由0&1組成的,包括source file, object file(.o), binary file等等,但vim會將所有的binary藉由ASCII轉換成為我們所看到的plain text,這裡以一main.cpp作為例子: main.cpp in vim #define N 81 int main(){ return 0;//this is the end } main.cpp, configured with  :%! xxd -b 00000000: 00100011 01100100 01100101 01100110 01101001 01101110 #defin 00000006: 01100101 00100000 01001110 00100000 00111000 00110001 e N 81 0000000c: 00001010 01101001 01101110 01110100 00100000 01101101 .int m 00000012: 01100001 01101001 01101110 00101000 00101001 01111011 ain(){ 00000018: 00001010 00001001 01110010 01100101 01110100 01110101 ..retu 0000001e: 01110010 01101110 00100000 00110000 00111011 00101111 rn 0;/ 0000...

Compile behind-the-scene

習慣使用了具備強大功能的整合工具-- IDE(e.g Visual Studio),執行source code(e.g .cpp)僅需點下  建置(Build)   然後  ▷  ,有時是只點下   ▷  ,就完成了許多希望程式去做的事,很方便,但也因此缺乏對於幕後工程的認識。離開了IDE,使用terminal則可以透過下面的指令完成同樣的事情: $ g++ main.cpp -o main.out #編譯 $ ./main.out #執行 helloworld 編譯透過以上一行簡單的指令,將我們寫的source code編譯成執行檔(在Linux上是.out,在Windows上則是.exe),然後可以直接被電腦執行。簡單的一句指令,過程則可以分為四個步驟,分別是1. 前編譯Preprocessing, 2. 編譯compilation, 3. 組譯assembly 以及 4. 連結linking。 以下用一支比helloworld更簡單的程式來呈現: main.cpp #define N 81 int main(){ return 0;//this is the end } 1. Preprocessing: .cpp -> .ii,處理#,刪除註解(//, /**/),加以編號。 $ g++ -E main.cpp -o main.ii main.ii: # 1 "main.cpp" # 1 "<built-in>" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "main.cpp" int main(){ return 0; } 2. Compilation: .ii -> .s,將 .ii檔進行分析以及最佳化,將高階語言翻譯成assembly code。屬於程式建構過程最複雜的環節。 main.s $ g++ -S main.ii -o main.s .file "main.cpp" ...

CMake vs Make

 在認識modmesh的過程中,包括modmesh本身以及延伸的小實作,幾乎處處可見make及CMake的身影;雖然對它們的認識甚少,但操作的過程中可以隱約感受到make與cmake似乎存在某種相依性,擁有類似的機制。同樣仰賴導演(make, cmake)與腳本(Makefile, CMakeList.txt),但卻做著不太一樣的事情,好像不只是差了一個C這麼簡單。 ~/git-repo/importation$ ls build CMakeLists.txt pybind11 test.cpp ~/git-repo/importation/build$ cmake .. ~/git-repo/importation/build$ ls CMakeCache.txt CMakeFiles cmake_install.cmake Makefile pybind11 ~/git-repo/importation/build$ make CMake vs make? 這裡 對於make做了些許的整理,make可以用來自動化shell script。CMake之於Make,與make之於shell script,存在了一些相似性。 「CMake 用來產生跨平台的專案建置文件,在 windows 下它會生成 visual studio 的專案檔 (.sln) codeblock eclipse,在 linux 下它會生成 Makefile。」在cmake之前的環境如下: ~/git-repo/importation$ ls CMakeLists.txt pybind11 test.cpp ~/git-repo/importation$ ls build/ (empty) 然後創建build這個directory,這能夠幫助我們將原始文件以及CMake過程的中間產物做做區分,再進行CMake: ~/git-repo/importation$ mkdir build ~/git-repo/importation$ cd build/ ~/git-repo/importation/build$ cmake .. 執行完成後,build底下就會有Makefile: ~/git-repo/importation/build$ ls CMakeCac...

Command Line 與 Makefile

在認識到Linux以前,我鮮少接觸到CLI(Command Line Interface),也花了些許時間去熟悉。一開始看它也許會感到有些震懾,但並沒有想像中的複雜,單純是將我們習慣使用的GUI(Graphical User Interface)改成CLI,滑鼠改成鍵盤,簡單做了轉換。 sudo apt-get install qt6-default //以superuser身份安裝qt6-default mkdir build/install -p //新增資料夾 cd build/install //切換目錄到build/install rm –rf build //remove文件, recursively. makefile make 以及 makefile讓我們得以自動化我們想執行的command line。比如說modmesh裡面中clean這個target,若是藉由一行一行的command line我們會需要輸入以下的指令, rm -f $(MODMESH_ROOT)/modmesh/_modmesh$(pyextsuffix) make -C $(BUILD_PATH) clean 但如果已經在Makefile中寫好了clean這個target,將一行行的command line寫成了shell script。 .PHONY: clean clean: rm -f $(MODMESH_ROOT)/modmesh/_modmesh$(pyextsuffix) make -C $(BUILD_PATH) clean 我們就可以去藉由make,直接輸入 make clean 去執行我們想要去執行的內容,不用逐步命令。 make clean

Write a module in C++ and use it in python

 做這個小實驗的當天看到這個梗圖,相當呼應這個主題: 「其它的程式語言對你作力學是沒用的,作計算就三本柱 Python、C++、Fortran 足矣,連 C 都沒什麼用處。」Python在計算的速度上相較於C++非常的緩慢,這個 demo 很清楚地呈現了這件事。 以計算力學為題,python在tool的開發,input的整合上具有優勢,但是在計算效能上的表現不佳,於是就有了許多與python互相支援的foreign function interface(FFI),如 swig, cython, pybind11。 截python所長,補C++所短 (or vice versa) ,似乎是做出更好的力學程式不可或缺的元素,pybind扮演的角色於是顯現。接下來就簡單用C++寫一個python的module: 1. 寫 .cpp/.h file。 #include <pybind11/pybind11.h> double square(double i){ return i*i; } PYBIND11_MODULE(test, handle){ //Module 的attributes 會在這裡做定義 handle.doc()="This is my doc"; handle.def("sqrt", &square); } 2. 寫 CMakeList.txt。 cmake_minimum_required(VERSION 3.4) PROJECT(pybind_vid) add_subdirectory(pybind11) pybind11_add_module(test test.cpp) //test為建構的module的名稱 test.cpp是它所依據的檔案 3. Build the module。 mkdir build cd build/ cmake .. make 4. 在python中使用前面所建立的module。 ~/git-repo/importation/test$ python3 >>> import test >>> dir(test) ['doc', 'file...