RabbitMQ 基本介紹
前言
本文主要使用了VScode + gcc工具,編譯除錯了孟寧老師的案例menu。
1、環境配置和編譯
1.1 下載編譯器:MinGW-w64 - for 32 and 64 bit Windows往下稍微翻一下,選最新版本中的x86_64-posix-seh
。
1.2 安裝並配置環境:將壓縮包解壓縮,找到bin資料夾的完整路徑,比如在本機上的路徑是C:\mingw64\bin,將路徑新增到環境變數的path中。具體操作如下:(Windows 10)此電腦-右擊-高階系統設定-環境變數,點開後,path中,新增上路徑C:\mingw64\bin。
1.3 驗證編譯器是否安裝成功:win + R, 顯示cmd回車:在終端命令列輸入gcc,提示no input files,說明安裝成功。輸入gcc -v 顯示當前安裝版本。
1.4 下載vscode,注意vscode只是一個純文字編輯器(editor),不是IDE(整合開發環境),不含編譯器(compiler)和許多其它功能,所以編譯器要自己裝好。在此不作贅述。
1.5 安裝vscode的拓展:
- C/C++:又名 cpptools,提供Debug和Format功能
- Code Runner:右鍵即可編譯執行單檔案,很方便;但無法Debug
1.6 配置檔案
首先新建資料夾(即工作區)test,開啟vscode,開啟此資料夾,在資料夾內寫了一個測試程式碼hello.cpp,如下:
VSCode
可以一鍵生成基礎配置檔案:
-
新建一個
.vscode
-
開啟你建立的 C 檔案,
F5
執行。不出意外的話會彈出配置引導面板,在彈出面板中依次選擇以下選項:- C++ (GDB/LLDB)
- gcc.exe - 生成和除錯活動檔案
稍等片刻,會自動在.vscode
資料夾下生成launch.json
tasks.json
。這樣生成的兩個配置檔案是相互匹配好的,可以直接用於基本的執行和除錯。 如果是 C++檔案,選擇g++.exe
編譯器即可。
在本專案中,需要生成的配置檔案如下:
c_cpp_properties.json
1 1 {
2 2 "configurations": [
3 3 {
4 4 "name": "Win32",
5 5 "includePath": [
6 6 "${workspaceFolder}/**"
7 7 ],
8 8 "defines": [
9 9 "_DEBUG",
10 10 "UNICODE",
11 11 "_UNICODE"
12 12 ],
13 13 "windowsSdkVersion": "10.0.17763.0",
14 14 "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.16.27023/bin/Hostx64/x64/cl.exe",
15 15 "cStandard": "c11",
16 16 "cppStandard": "c++17",
17 17 "intelliSenseMode": "msvc-x64"
18 18 }
19 19 ],
20 20 "version": 4
21 21 }
launch.json
1 {
2 "version": "0.2.0",
3 "configurations": [{
4 "name":"g++.exe-生成和除錯活動檔案", // 配置名稱,將會在啟動配置的下拉選單中顯示
5 "type": "cppdbg", // 配置型別,cppdbg對應cpptools提供的除錯功能;可以認為此處只能是cppdbg
6 "request": "launch", // 請求配置型別,可以為launch(啟動)或attach(附加)
7 "program": "${fileDirname}/${fileBasenameNoExtension}.exe", // 將要進行除錯的程式的路徑
8 "args": [], // 程式除錯時傳遞給程式的命令列引數,一般設為空即可
9 "stopAtEntry": false, // 設為true時程式將暫停在程式入口處,相當於在main上打斷點
10 "cwd": "${workspaceFolder}", // 除錯程式時的工作目錄,此為工作區資料夾;改成${fileDirname}可變為檔案所在目錄
11 "environment": [], // 環境變數
12 "externalConsole": true, // 使用單獨的cmd視窗,與其它IDE一致;為false時使用內建終端
13 "internalConsoleOptions": "neverOpen", // 如果不設為neverOpen,除錯時會跳到“除錯控制檯”選項卡,你應該不需要對gdb手動輸命令吧?
14 "MIMode": "gdb", // 指定連線的偵錯程式,可以為gdb或lldb。但我沒試過lldb
15 "miDebuggerPath": "gdb.exe", // 偵錯程式路徑,Windows下字尾不能省略,Linux下則不要
16 "setupCommands": [
17 { // 模板自帶,好像可以更好地顯示STL容器的內容,具體作用自行Google
18 "description": "Enable pretty-printing for gdb",
19 "text": "-enable-pretty-printing",
20 "ignoreFailures": false
21 }
22 ],
23 "preLaunchTask": "Compile" // 除錯會話開始前執行的任務,一般為編譯程式。與tasks.json的label相對應
24 }]
25 }
tasks.json
1 {
2 "tasks": [
3 {
4 "type": "shell",
5 "label": "C/C++: g++.exe build active file",
6 "command": "C:\\mingw64\\bin\\g++.exe",
7 "args": [
8 "-g",
9 "${file}",
10 "-o",
11 "${fileDirname}\\${fileBasenameNoExtension}.exe"
12 ],
13 "options": {
14 "cwd": "${workspaceFolder}"
15 },
16 "problemMatcher": [
17 "$gcc"
18 ],
19 "group": {
20 "kind": "build",
21 "isDefault": true
22 }
23 }
24 ],
25 "version": "2.0.0"
26 }
1.7 執行檔案,點選F5,成功除錯。
2.模組化設計
模組是指整個系統中一些相對對獨立的程式單元,每個程式單元完成和實現一個相對獨立的軟體功能。通俗點就是一些獨立的程式段。 模組設計也叫詳細設計,是系統設計階段後續的一個軟體開發階段。在系統設計階段要把整個應用問題分解成一個個獨立的功能部分--叫做程式模組。 每個程式模組要有自己的名稱、識別符號、介面等外部特徵。
模組化設計和程式設計有以下幾點好處:
1、便於設計與程式設計
2、便於分工合作 對於較大的專案這種方式的好處最為明顯。
3、便於除錯 可先對每個小模組進行單獨除錯,發現問題快,解決也快。在每個小模組都檢測通過後,整體調試出現問題只要檢查各模組相關聯的部分(如引數地址、引數型別)是否統一即可。
4、便於移植 其他專案中如果有相同的應用,可以直接複製。如果只是近似應用,也只需做區域性小改動即可。可省去大量的不必要的重複工作。5、便於改進
模組獨立程度的2個定性度量標準
•內聚:模組內各元素的相關程度
•耦合:模組間的互動程度
整個專案的開發過程可以清楚的看到模組化思想:
3.介面的可重用性
一般來說,介面規格包含五個基本要素:
1.介面的目的;
2.介面使用前所需要滿足的條件,一般稱為前置條件或假定條件;
3.使用介面的雙方遵守的協議規範;
4.介面使用之後的效果,一般稱為後置條件;
可重用介面,則是其他程式設計師在重用這個介面時應該不需要了解這個介面內部程式碼的組織方式,只需要瞭解呼叫介面和生成的目標檔案,就可以方便的將介面整合到自己的軟體中。
如下述程式碼就用到了很多介面:
1 typedef struct LinkTableNode
2 {
3 struct LinkTableNode * pNext;
4 }tLinkTableNode;
5
6 typedef struct LinkTable tLinkTable;
7
8 tLinkTable * CreateLinkTable();
9
10 int DeleteLinkTable(tLinkTable *pLinkTable);
11
12 int AddLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
13
14 int DelLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
15
16 tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode, void * args), void * args);
17
18 tLinkTableNode * GetLinkTableHead(tLinkTable *pLinkTable);
19
20 tLinkTableNode * GetNextLinkTableNode(tLinkTable *pLinkTable,tLinkTableNode * pNode);
4.執行緒安全問題
執行緒安全是多執行緒程式設計時的計算機程式程式碼中的一個概念。在擁有共享資料的多條執行緒並行執行的程式中,執行緒安全的程式碼會通過同步機制保證各個執行緒都可以正常且正確的執行,不會出現資料汙染等意外情況。
常見的解決執行緒安全的方法有:
- 同步方法&靜態同步方法
- 使用Lock鎖
- 同步程式碼塊
例如下述程式碼:
1 /*
2 * Delete a LinkTable
3 */
4 int DeleteLinkTable(tLinkTable *pLinkTable)
5 {
6 if(pLinkTable == NULL)
7 {
8 return FAILURE;
9 }
10 while(pLinkTable->pHead != NULL)
11 {
12 tLinkTableNode * p = pLinkTable->pHead;
13 pthread_mutex_lock(&(pLinkTable->mutex));
14 pLinkTable->pHead = pLinkTable->pHead->pNext;
15 pLinkTable->SumOfNode -= 1 ;
16 pthread_mutex_unlock(&(pLinkTable->mutex));
17 free(p);
18 }
19 pLinkTable->pHead = NULL;
20 pLinkTable->pTail = NULL;
21 pLinkTable->SumOfNode = 0;
22 pthread_mutex_destroy(&(pLinkTable->mutex));
23 free(pLinkTable);
24 return SUCCESS;
25 }
在第13行通過給訊號量加鎖,16行解鎖,實現了多程序在刪除連結串列時的互斥操作,保證了執行緒的安全。
總結:
通過孟老師的menu案例,我學習了軟體工程設計中的模組化設計思想、介面的可重用性和多執行緒安全等知識。
reference:
https://gitee.com/mengning997/se/blob/master/README.md#%E4%BB%A3%E7%A0%81%E4%B8%AD%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B