802.11a所規範的實體層,主要以正交分頻多工(orthogonal frequency division multiplexing,簡稱OFDM)技術為基礎,來提升傳送的速率(跟802.11比起來)。
OFDM-Orthogonal Frequency Division Multiplexing 正交分頻多工:是一種高效率的多通道調變解調變技術。利用離散快速傅利葉轉換(FFT)和反快速傅利葉轉換(IFFT)來調變和解調變傳送的訊號。可使用的頻寬被劃分為多個狹窄的頻帶,資料就可以被平行的在這些頻帶上傳輸。
以無線電波(radio wave)為實體層,還須要比較複雜的PHY。
802.11將PHY進一步劃分為兩個組成元件:
一個是實體層收斂程序(Physical Layer Convergence Procedure簡稱PLCP),負責將MAC訊框對應到傳送媒介;
另一個是實際搭配媒介(Physical Medium Dependent,簡稱PMD)負責傳送這一些訊框。
PLCP橫跨MAC與實體層,在802.11網路中,PLCP將PLCP將訊框傳至空中之前,會在其中加入一些欄位。
802.11四種實體元件
1. Station:工作站-配備無線網卡的行動裝置
2. Access Point:基地台-位於工作站與傳輸系統之間的橋接器
3. Wireless medium:無線媒介-802.11標準以無線媒介在工作站之間傳遞訊框。其所定義的實體層不祇一種;這一種架構充許多種實體層同時支援802.11 MAC。
4. Distribution System:即有線骨幹網路-當幾部基地台串連以覆蓋較大區域時,彼此之間必須相互通訊,纔能夠掌握行動式工作站的行蹤。而傳輸系統(distribution system)屬於802.11的邏輯元件,負責將訊框(frame)轉送到目的地。
網路類型
Basic Service Set,簡稱BSS:由一組彼此通訊的工作站所構成。工作站之間的通訊的區域稱為Basic Service Area
而BSS又主要分為兩種:Independent BSS(IBSS)、Infrastructure BSS
Infrastructure BSS:如有必要與其它工作站通訊,必須經過兩個步驟
(1). 首先,由啟始對話的工作站將訊框傳遞給基地台
(2). 其次,由基地台將此訊號框轉送至目的地
換句話說,成員之間的通訊必需要通過Infrastructure
Independent BSS(IBSS):在成員之間,若互相在通訊範圍內的話,不需透過Infrastructure,成員之間可以直接通訊
Extended Service Set:簡稱ESS:將幾個BSS串連為ESS,所有位於同一個ESS的基地台將會使用相同的組合識別碼(service set identifier,簡稱SSID)
為了讓ESS裡的工作站能夠彼此通訊,無線媒介必須能在第二層進行連線,由於基地台扮演橋接的角色,因ESS裡的工作站若要彼此通訊,則骨幹網路必需在第二層連線。第一代基地台必需透過Hub或virtual LAN才能與第二層連線,新型的產品中已內建tunneling技術,可以模擬第二層的連線環境。
802.11所提供的行動性,存在於鏈路層的基本服務組合之間。鏈路層以上究竟發生什麼事,它並無法理解。在部署規劃802.11時,網路工程師必需特別小心,好讓網路層的工作站IP位址,可以在實體層進行無間隙轉換(seamless transition)時被保存下來。就802.11而言,基地台出現三種轉換
1. 不轉換:在同一個BSS中
2. BSS轉換:在同一個ESS中,但是,BSS不相同
3. ESS轉換:在802.11中,並不支援這一種轉換~最多就是把之前的連線關掉,連上新的ESS。而這個就是handover,在同質無線網路中,就是所由的水平式的handover,在異質網路中,就是垂直的handover。在802.21就是提出來讓802.X中異質網路可以達成無間隙的handover。
2008年9月30日 星期二
802.11網路概論
無線網路導論
無線網路優點
1. 行動性
2. 部署容易、建置快速
3. 彈性
4. 後期成本低
Wireless bridge (無線橋樑)
Access Point (無線基地台)
Wireless Interface (無線網卡)
無線網路所使用的媒介不像實體線纜有明確定義的路徑,而祇是經過特殊編碼與調變過的無線電波鏈路。
IEEE標準 | 速度 | 頻段 | 附註 |
802.11 | 1Mbps 2Mbps | 2.4 GHz | 首份PHY標準(1997)。同時支援跳頻與直接序列調變技術。 |
802.11a | 最大可到54Mbps | 5GHz | 第二份PHY標準(1999),產品遲至2000年末才推出 |
802.11b | 5.5Mbps 11Mbps | 2.4GHz | 第三份PHY漂準 |
802.11g | 最大可到54Mbps | 2.4GHz | 第四份PHY標準(2003) |
無線電本質上屬於一種廣播媒介。一部工作站進行傳送時,所有其它工作站祇能聆聽。基地台的角色有一點像是以往的分享式Ethernet集線器,每一部基地台的傳輸能力固定,且必須由所有連線用戶共享。要增加網路的容量,網管人員必須添加基地台,同時縮小現有的基地台的覆蓋範圍。
無線網路工作原理?
什麼是無線網路系統呢?
2008年9月27日 星期六
UML
這一個學期一開始本來要選的課「物件導向程式設計」中使用的課本有提到UML這一個東西~讓我花了一點時間去找相關的資料~耶~針對物件導向程式設計(Java/C++)感覺好像很有用耶~
雖然還沒有開始讀,但是,我已去圖書管借了3本書回來看了~
總之呢~UML是就幫助我們了解程式的文件的一種,而主要是由圖型來表示~若我們在閱讀其他人程式的時候,若直接去由程式碼下去看,若程式很小時那還好,但是,若程式非常龐大,我們就必需要假定它其它部分是沒有問題了,而只去看我們要修改或是負責的部分~但是,還是要了解整個系統的架構,這個時候就必需要看文件或是架構圖~就好像建房子一樣,我不可能去看每一個角落是怎麼建立的~每一個人都要負責好自己的地方~interface的要建構好~
就好像硬體-韌體-軟體
每一個都有自定好的interface給上面使用,而上面的人只要依照下層給的規格去建立自己的程式,有問題再跟下面反應,這就是分層的觀念~
以下節錄至網路上:
UML是什麼?
UML是Unified Modeling Language的簡稱,中譯為「統一塑模語言」。其中:
●Unified:UML是一種標準語言,廣泛運用於全世界。
●Modeling:UML用途在於塑模(Modeling),也就是畫軟體藍圖。
●Language:UML是一種塑模語言,而非程式語言或標示語言。
也就是說,UML是軟體系統發展人員用以建造模型,而這些模型使得工作團隊能夠:將系統具象化(Visualization)、將系統結構及行為規格化 (Specification)、建構(Construction)系統、以及記錄(Documentation)發展系統過程中之各項決策。
什麼是塑模?
作曲家會將其腦袋中的旋律譜成樂曲,建築師會將其設計之建築物畫成藍圖,行銷廣告人員會將其創意製作成簡報;這些樂曲、藍圖及簡報就是模型(Model),而建構這些模型的過程就稱為塑模(Modeling)。
軟體開發如同音樂譜曲及建築設計,其過程中也必須將需求、分析、設計、實作、佈署等各項工作流程之構想與結果予以呈現,這就是軟體系統之塑模。
為什麼要塑模?
絕大部份的音樂演奏都需要樂譜(除了少數即性式表演外)!
絕大部份的建築施工都需要藍圖(除非要蓋的是一間狗屋)!
同樣的,所有軟體系統的建構最好都有適當的分析設計藍圖,因為軟體開發的過程絕對不是任意的、隨性的、且戰且走的、天馬行空的。
UML在軟體塑模中所扮演的角色是什麼?
軟體發展之方法論中包含了程序(Process)及表示法(Notation)兩個部份,其中:
●程序指的是系統開發的流程,例:瀑布模式、漸增模式、擴展模式、雛型模式、螺旋模式等。
●表示法指的是建構軟體模型中所會用到之符號及規則。
UML所涵蓋的內容是表式法而非程序,UML是與程序無關的(Process Independent),也就是說,無論以任何程序來開發軟體系統,都可以使用UML來建構軟體模型。
UML與物件導向方法之關係
●UML之訂定與物件導向方法的確有非常密切之關係。
●UML中的各種符號及規則與物件導向語言(Java,C++)之結構有完整對應。
●但是,UML絕對不僅限用在物件導向軟體開發,UML中有些概念與圖形甚至可說是與物件導向無關,
例:Use Case Diagram及Statechart Diagram
●因此,軟體開發時無論是否採用物件導向方法,UML都是適用的。
UML的重要性
●UML是OMG公佈的官方標準。
●UML已為全世界軟體業者所廣泛採用,各大軟體公司(Microsoft、IBM、Oracle等)
在其產品中均支援UML。
●UML的應用領域越來越廣(資料庫設計、韌體設計、資訊管理等)。
UML的現行版本
UML現行版本為1.5版(http://www.omg.org/technology/documents/formal/uml.htm),但2.0版將近完成,應會在短期內正式公佈(http://www.omg.org/uml)。
UML的內容到底是什麼?
UML對於軟體開發相關人員而言,其實就只是一組符號及規則,其中包括:
1.Basic Building Blocks(都有其相對的符號)
(1) Things
●Structura˙Things:Class、Interface、Collaboration、Use Case、Active Class、Component、Node
●Behaviora˙Things:Interaction、State Machine
●Grouping Things:Package
●Annotation Things:Note
(2) Relationships:Association、Generalization、Dependence、Realization
(3) Diagrams
●Structural:Class、Object、Component、Deployment
●Behavior:Use Case、Activity、Statechart、Sequence、Collaboration
2.Rules(符號的使用規則)
Name、Scope、Visibility、Integrity、Execution
3.Common Mechanisms(各類符號及圖形通用的機制)
Specification、Adornments、Common Division、Extensibility Mechanisms
如何學習UML?
●找本淺顯易懂的入門書籍,先掌握UML的全貌,千萬不要被過多抽象的軟體工程專有名詞所絆住。記住:UML只是一組符號而已!
●先學習讀圖,讓自己先習慣於UML之各種符號,尤其注意UML中以擴充機制(Extensibility Mechanisms)所產生之符號,此部份最容易使初學者迷惑。
●練習畫圖,訓練自已將心中之構想以UML符號呈現出來,注意各類符號之正確表示法,不要隨意更改之。
●選用適當之CASE工具,Rationa˙Rose,Microsoft Visio,Borland Together都是很好的軟體工具。
如何應用UML於軟體開發?
●選擇一個適當之開發程序(Process),例:RUP
●選擇一個適當之UML發展工具,例:Rationa˙Rose
●相關人員接受完整之訓練
參考資料:
淺談UML
為何要使用 UML?
頻寬
這裡要說明頻寬這一個東西~
其實早在碩一上剛進來的時候,就要先了解無線網路通訊的DSRC的基本觀念~
那一個時候還沒有無線是波的觀念~所以,一直搞不懂什麼是頻寬,難到是每一秒傳多少單位的頻寬嗎?
直到現在才真的有一點概念了~
不過,除了類比和數位訊號的差別,主要的是由這裡來得知的知識~
當然要整理一下囉~
頻率:一個波在一秒鐘震動的次數 也就是說 1Hz代表一秒鐘震動一次,1KHz代表一秒鐘震動1,000次,1MHz代表一秒鐘震動1,000,000次!!!
無論是有線電與無線電傳輸都有一個中心頻率在,ADSL的傳輸頻率在25KHZ~1.1MHz,手機的傳輸頻率大家都知道900MHz(or 1800MHz)
電學上的頻寬:而我們在這裡有說過,在傳送端與接收端產生一個相同頻率與相位的載波是不容易的,且訊號在傳送的過程中,有可能會有些微的變化,因此,當你設定傳送出去的訊號頻率為G Hz,那它會有一個頻寬B Hz,就就是說在G正負B/2 Hz都是屬於這一個訊號的傳送接收範圍~這就是無線通訊常說的頻寬(也就是要接收的頻率範圍)~
電學上的頻寬:也就是說有線電與無線電傳輸都有一個中心頻率,這裡不直接說頻率而說"中心頻率"因為在傳輸電波的過程中頻率其實並不是固定的,因為傳輸信號的時候因為解調變的動作以及傳輸資料的大小(以無線電來說聲音也是資料的一種),頻率會在一個範圍裡面上下波動,這個波動的範圍就是所說的頻寬,可以想像一下假設一個頻率代表一條線,如果有10個頻率就代表同時有10條線在傳輸資料,相對的傳輸的資料量就可以增加。因此無線電裡面所說的頻率455MHz頻率,頻寬5KHz的意思其實是中心頻率455MHz做上下2.5KHz範圍的移動!!(但是中間會相隔 0.5KHz的帶寬,所以實際上只有4個帶寬在用)
保護帶:而另外一提的~每個通道頻寬B Hz,為了防止互相干擾,通道間以沒有使用的頻譜(稱保護帶guard band)做分隔~
而無線的頻率高跟低其實跟傳送資料的速率是沒有關係的~頻率高不代表頻寬越大(這裡指的應該就是傳送速率),就好比數字由1~10,他的內容絕不會超過10,數字91~100他的內容也絕不會超過10,頻率越高他的衰減db值越大,有線與無線都一樣
剛才提過ADSL的頻率範圍是25KHZ~1.1MHz,也就是說以電學的角度來看,ADSL的頻寬將近1.1MHz,不過這裡就產生了另外一個問題!! 中華電信不是都說寬頻的頻寬有2~8M嗎?這裡指的並不是剛才所說的真實頻寬!!2~8M所說的是經過數位調變並且壓縮之後的"傳輸速率"!!!他只是經過換算之後對比電學傳輸頻寬的寬度.
而附帶一提的是,中華電信給我們的ADSL的傳送速率是bit/sec為單位
而我們電腦使用的是計算速率是以byte/sec為單位
而1 byte=8bit
參考資料:
有線電跟無線電所指的頻寬是否相同?
Office 2007 建立PDF檔案
在網路上找到這一篇文章~
嗯,其實我覺得透過Office自己轉似乎比較好一點哩~
直接到微軟網站下載
安裝完後,在檔案另存新檔會出現另為PDF檔,就這樣。以下有網站可以參考~
Office 2007 建立PDF檔案
無線的基本概念~
這一個禮拜完全沒有進度~
因為,我生病了~
那就把之前的進度拿出來寫吧~
前不久去參加「通訊系統模擬課程訓練與推廣」、「異質無線網路整合與漫遊技術研討會」。
對我這一個無線網路初學者都算是有收護啦~
不過,真的只是概念而以~
首先,先介紹一下無線網路的非常基本的概念吧~
這是在「通訊系統模擬課程訓練與推廣」學到了~
這一門課是教說如何透過Matlab去模擬數位訊號與類比訊號之間的轉換~
訊號的轉換的種類
類比訊號-類比訊號-類比訊號(例如廣播)
數位訊號-類比訊號-數位訊號(用數據機上網)
類比訊號-數位訊號-類比訊號(視訊會議系統)
數位訊號-數位訊號-數位訊號(數位資料編碼)
在真實世界中,在傳送訊號有傳送端與接收端~
傳送端:調變(modulation)
接受端:解調(demodulation)
有點像是編碼與解碼~
另外有一點要注意的是,傳送端與接收端必需使用相同的載波(也就是轉換function和inverse function),才能把原來的訊號解析出來~
這裡有課堂上使用到的例子,我覺得還蠻清楚的,就把它記錄下來吧~
這一些對有上過通訊系統的課的人應該會覺得很簡單吧~
基頻訊號:是指未經調變等方式處理過的自然訊號(可以為類比或數位型式),如語音和影像訊號。
載波:是指被調製以傳輸信號的波形,一般為正弦波。一般要求正弦載波的頻率遠遠高於調製信號的頻寬,否則會發生混疊,使傳輸信號失真。
訊號頻率遷移(訊號調變技術)屬於前述第一種類型之轉換。此轉換(類比調變)是將原始的基頻訊號轉換到高頻的訊號,經由類比調變後的高頻訊號稱為已調變訊號(modulated signal)。
大家已熟知一般無線通訊系統之收發機都需要天線將訊號做幅射或接收,依據天線理論,天線的長度(或大小)與所幅射或接收之訊號的頻率有很重要的關係,例如,常聽到的1/4波長天線表示天線的大小是所要幅射或接收之訊號波長的1/4倍。考量頻率為3 kHz的音頻訊號,其波長為3*10^8/3*10^3=10^5(公尺)
若要直接將此訊號直接幅射,所需天線的長度為10^5/4=25000(公尺)
另外考量一100 MHz的訊號,其波長為3*10^8/100*10^6=3(公尺)
若要幅射或接收此訊號所需天線的長度為3/4=0.75(m)
以上分析可知天線大小是與訊號的頻率成反比的,要傳送的資料訊號為基頻訊號,其頻率都比較低。因此若要以無線方式傳送基頻訊號,考量天線的實際狀況勢必要將基頻訊號轉移至較高的頻帶(透過傅利葉轉換)再傳送,也就是必須有一種「頻率遷移」技術以達到無線傳輸的目的。
前述這種訊號頻率遷移與訊號取回之程序稱為調變(modulation)與解調(demodulation),利用前述之調變與解調技巧可建立一個簡易訊號傳輸系統(如下圖所示),其中稱為載波頻率(carrier frequency);通道可以是有線或無線。
簡易訊號傳輸系統在傳送端與接收端皆使用相同的載波,此種使用相同載波的系統稱為同調系統(coherent system),在傳送端與接收端產生一個相同頻率與相位的載波是不容易的。
另一個觀念:分頻多工
多個相同頻帶的訊號移至不同頻帶使用同一個傳輸媒介傳送的方式,是順理成章的一種多工技術,我們稱之為分頻多工(frequency division multiplexing, FDM)。
一個簡單的分頻多工系統的架構如下圖所示,多工器以載波頻率、和分別將4個輸入訊號調變到不同的頻帶(稱之為通道channel),每個通道頻寬B Hz,為了防止互相干擾,通道間以沒有使用的頻譜(稱保護帶guard band)做分隔,以此方式在單一傳輸媒介內同時傳送4個訊號之目的。
以下這一張圖,就是數位訊號透過類比訊號傳送出去,把真正的數位訊號藏在類別訊號中,也就是數位訊號-類比訊號-數位訊號之間轉換的例子
以下例子是類比訊號-類比訊號-類比訊號中的調幅(改變的是訊號的振幅)
虛線是原始訊號、而實線是實際在空氣中傳送的訊號
以下例子是類比訊號-類比訊號-類比訊號中的調頻(改變的是訊號的頻率)
第一個圖是原始訊號
第二個圖的紫色是調頻之後的訊號
第三個圖是解調頻之後的訊號
2008年9月17日 星期三
軟體工程
最近在決定要修什麼課~
因為,最近在要修改學長的程式~在使用Qt,也就是C++的延伸~
所以,本來預定要選修「物件導向軟體工程」的,但是,很可惜的是,
課程使用的課本是用java語言的,而C++與java又非常的像~
因為,我C++也不是很熟~很怕被同時搞混~
所以,目前決定先不要選「物件導向軟體工程」這一門課~
目前的決定是:
打算選「軟體品質管理」,然後,旁聽「英文」、「 電腦通訊網路」、「 模糊邏輯」。
在聽過我們成大資工軟體大老「朱治平教授」,上的這兩門課之後,對軟體有一些新的認識~
這裡把它整理出來吧~
物件導向出來之前,我們寫一個系統是用功能去細分的,像是一個提款機,它有很多功能,我們就一直把它細分成許多功能~細分成不能在細分之後,就由最小的功能慢慢的寫到整個系統~
而物件導向出來之後,我們就是把系統分成許多「元件」,而「元件」是由許多的物件所組合而成的~而「元件」和「功能」最大的差別在於re-use。
只要可以增加re-use的比率,我們就可以減少re-work的比率,就可以多花一點時間在增加軟體品質上,而什麼叫作軟體的品質,這又是一個大問題~在軟體分為「功能面」與「非功能面」,而非功能面要如何量化~像是如何去計算寫這一個程式要花多少成本,也是一個目前的問題~
而軟體主要的功能有兩個部分~
1. 是輔助的角色:像是嵌入式的系統,主要是focus在硬體上面,軟體只是去如何操作這一個硬體。
2. 是主要的角色:像是office,電腦上的應用程式;硬體只是讓軟體可以在上面操作的一個輔助角色。
而老師在上課也有提到一些重點,軟體有其獨特性:
1. 軟體修改容易:假設我們寫了一個系統,在其中一個output出現錯誤~這個時候我們可能知道大概哪裡出了問題,這個時候我們把它作部分修改之後,測試ok,output正常,那就完成了~問題是,會不會還有其它元件,會使用到這一個部分~但是,我們沒有針對它去測試,直到最後,一堆隱藏的問題本來不會浮現,一起出現時,就會出現問題~就像豆腐和波菜,分別吃不會有問題,一起吃就會出現問題~
2. 軟體複製容易:若與硬體廠商做比較,硬體廠商在完成一個成品之後,之後要量產時,仍然需要一堆硬體成本~而軟體的話,像是你幫一家公司設計了一個人事管理系統,當要替第二家公司也設計人事管理系統時,這個時候你所需要的成本就相對的非常的少了~
3. 軟體不容易測試:同樣的也是相對硬體來說,當你設計好一個洗衣機時,如果要測試是否合格,那麼最多只是加入不同量的衣服來測試它的極限~但是,依軟體來說~很難說要拿哪一些情況來測試這一個程式,因為,可能性是在太多了~老師上課說了一個例子,就像100個迴圈,用最簡單的情況來說~若只有false與true兩個情況,那麼就有2的100次方個情況~
軟體工程就是學如何做好專案管理:若文件寫的好,有照一定的規範走,就算公司新人來也可以馬上接下來~若管理的不好,設計師一走,整個專案馬上就掛點~
而在設計一個管理系統時,軟體就是一個工具,仍然需要domain knowledge;像是客運的管理,薪水的管理、進貨存貨管理~這一些都是需要domain knowledge的~
而我目前自己想了一下,寫程式的程序應該是這樣~
思考架構(若遇到不確定程式是否有支援我們的需求可以寫一個單元程式來試試看)-撰寫程式(最好每寫一個程式,然後,單元測式)-測試整體程式
但是,基本上,應該大部分的程式設計師都沒有做到那麼詳細吧~反正,先把程式趕出來再說~誰管你後面的人接的如何啊?
軟體工程絕對是有用的,最佳的實例就在印度。你只消看看印度的軟體產業,如此講究軟體工程,而且開發軟體的成績如此輝煌,你就應該知道:軟體工程除了可以拿來發表論文幫助學生取得學位或幫助教授升等之外,也確實是可以幫助軟體工業的。
可以參考這兩篇文章
軟體工程的弔詭、沒人在乎軟體工程
另外一提:在成大要取得「軟體工程學程」要修過五門課~
三門必修:軟體工程、物件導向軟體工程、CMMI
選修(選兩門):(PSP)Person Software Process、軟體品質、軟體度量
就是因為軟體彈性很大,所以,才不易整合~倘若像硬體功能簡單化,就很容易管理了~
但是,彈性大就是軟體的特性,因為,我們必需要制定一些規範來統一文件的撰寫方式~
CMMI與大便風牛肉麵
成也 CMMI ,敗也 CMMI?
2008年9月9日 星期二
工作管理 - 前景&背景執行
在很多情況,在執行一個程式之後,例如是telnet後,突然想到其它事,需要shell來讓你打其它指令~這個時候又不能把telnet關掉~我們有一個辦法,就是把它踢到背景去執行~這個時候我們就可以用shell了~
基本上我們執行一個指令,通常會等到執行結束,系統才會歸還shell給我們~
[root@host ~]# telnet ptt.twbb.org
但是,如果我們要一開始執行這一個指令就是在背景執行,就是要用到&這一個關鍵字
例:一開始執行telnet就是在背景執行
[root@host ~]# telnet ptt.twbbs.org &
我們如何知道現在有哪一些背景程式在執行哩?
[root@host ~]# jobs
[1]- Stopped telnet ptt.twbbs.org
[2] Running find / -name good &
[3]+ Stopped sudo updatedb
而那個 + 代表目前在背景下預設被取用的那個工作 (與 fg 這個指令有關 )!
那我如何把find的這一個程序呼叫到前景來執行哩~要用到fg的指令。因為,它的序位是2所以我們要打以下指令
[root@host ~]# fg %2
而相反的,把前景的程序踢到背景暫停,就必需要用到快捷鍵ctrl+z,注意喔~它目前是在背景中暫停,但是,沒有執行喔~
那如何讓它在背景中執行哩~那就要用到bg的指令囉~
[root@host ~]# bg %3
這個時候編號第三的程序就會在背景中執行了~
若突然想要中止程序,那就必需kill的指令
[root@host ~]# kill -9 %3
特別留意一下, -9 這個 signal 通常是用在『強制刪除一個不正常的工作』時所使用的, -15 則是以正常步驟結束一項工作(15也是預設值),兩者之間並不相同呦!
舉上面的例子來說, 我用 vi 的時候,不是會產生一個 .filename.swp 的檔案嗎? 那麼,當使用 -15 這個 signal 時, vi 會嘗試以正常的步驟來結束掉該 vi 的工作, 所以 .filename.swp 會主動的被移除,但若是使用 -9 這個 signal 時, 由於該 vi 工作會被強制移除掉,因此, .filename.swp 就會繼續存在檔案系統當中。 這樣您應該可以稍微分辨一下了吧?
所以,基本上我若要用kill,我都先不會打-9的參數,若真的殺不掉,再打-9的參數吧~
參考資料:
多工環境
鳥哥的Linux私房菜 - 程序與資源管理
2008年9月7日 星期日
linux-指令-awk
awk是可以用來分析文件的工具~本來我以為是一個小工具~
經過這一次之後,我才發現awk可以做的事情實在是太多了~可以由我上一篇寫的文章(svn update script)內的程式碼就知道了~
基本上呢,鳥哥寫的很清楚了,可以先看一下這裡~
那我在這裡寫的就是我有用到,但是,鳥哥沒有寫的~
如何把shell的變數傳給awk,這裡要注意的是,傳送去的變數,在使用的時候,不需要加$
[root@host ~]# awk -v var=$shell_var '條件類型1{動作1} 條件類型2{動作2} ...'file
如何在awk中,使用shell的指令,把command的output傳給awk下的var變數,而我的輸入部分就是透過command來完成的,可以參考我的上一篇的程式碼
command | getline var
另外,在awk的{動作1},其實可以放很大的程式碼,可以參考我上一篇文章的程式或是man awk
還有另一個很好用的指令system("指令")。就是可以在awk中,要求執行一個shell中的指令
例:
awk -F: '/正規表示法/
{
cmd="命令字串";
print cmd;
system(cmd)
}' file
參考資料:
好用的 awk 命令
AWK 中如何利用系統資源
AWK Tutorial Guide(英文)
臥龍小三 Shell 設計入門 8.正規表示式 awk
study-area Scripts大集合: awk
通用線程:Awk 實例,第一部份(簡體中文)
通用線程:Awk 實例,第二部份(簡體中文)
通用線程:Awk 實例,第三部份(簡體中文)
svn update script
因為最近在使用svn,
每次有新的進度之後,就要開始看哪一些需要更新,
有時候編譯出來的檔案實在有夠多~
不可能一個指令一個指令下去打,很浪費時間~
但是,又要更新,這是一定要做的,所以,今天就研究了一下,
看能不能寫一個script來幫助我update這一些資料
所以,研究了awk這一個小工具,真的很好用,可以用來分析文件中的資料~
研究了六個小時左右終於寫出來了~這一個東西以後真的可以幫我省六個小時回來嗎?
[2008/11/20補充]
在這幾個月用下來,我覺得真的還不錯用~
以下是我寫出來的script,要放在svn的目錄下才可以使用
update.sh
#!/bin/bash
#把svn status 的結果送到temp檔
svn status > temp
#抓行數
total_line=`awk '{print NR}' temp|tail -n1`
#迴圈
for ((current_line=1;current_line<=$total_line;current_line=current_line+1))
do
awk -v current=$current_line -v total=$total_line '{
if ($1=="?" && current==NR && $2!="temp")
{
printf("========================================\n");
printf("%s\n",$0);
printf("Do you want to add(a) or delete(d):");
"read yn && echo $yn" | getline yn;
if (yn == "a")
{
cmd = "svn add "$2;
print(cmd); // debug用
system(cmd);
}
else if (yn == "d")
{
cmd = "svn delete --force "$2;
print(cmd); // debug用
system(cmd);
}
}
else if ($1=="!" && current==NR && $2!="temp")
{
printf("========================================\n");
printf("%s\n",$0);
printf("Do you want to revert(r) or delete(d):");
"read yn && echo $yn" | getline yn;
if (yn == "r")
{
cmd = "svn revert "$2;
print(cmd); // debug用
system(cmd);
}
else if (yn == "d")
{
cmd = "svn delete "$2;
print(cmd); // debug用
system(cmd);
}
}
}' temp
done
#刪除暫存檔temp
echo "========================================"
rm -rfv temp
NR是表示目前是第幾行,current和current_line記錄目前是第幾行;total和total_line是記錄temp一共有幾行。
這裡要說明一下,我的effort。
一開始我是打算全部都用awk來完成我的目標,awk是可以分析檔案的內容作適當的動作。
但是呢?在svn的顯示要更新的列表我目前只有兩項要注意的「!」、「?」
「?」:就是表示server沒有檔案,client有檔案。在這一個情況下我有兩個可能的動作要做;
一、這一個資料是我剛剛新增的,所以,我應該要打svn add path指令
二、這一個資料是Makefile幫我建出來了,我不想要它,我要打svn delete --force path的指令
「!」:這一個表示server有檔案,但是,client端確沒有檔案。在這一個情況下我有兩個可能的動作;
一、這一個本來就是我想要刪掉,或是我打Makefile打令把它刪掉的,要打svn delete --force path指令
二、這一個就是不小心被我刪掉了資料,我必需要還原它,要打svn revert path指令還原它
這裡遇到一些問題,
一、awk沒有提供function讓使用著在程式執行時輸入資料,這樣就不能跟使用者互動了,還好,awk有提供一個指令command | getline var透過shell的command傳值給var變數。因此,input的部分我必需透過shell的read指令來幫助我~
二、非常意外的,在同一個awk中,command | getline var竟然只能執行一次,而之後若要重覆執行,就會讀取之前輸入的資料,因此,我必需透過shell script讓每分析新的一行,我必需重新執行awk,而每一次執行awk,我必需只讀取我要分析的那一行,不然,又是由第一行開始,那第一行就會執行command | getline var,那我就前功盡棄啦~
三、我必需要知道這一個文件有幾行~不然,我怎麼去設定迴圈哩~
四、shell的變數與awk裡面的變數是不相同的,我必需透過-v參數把total_line與current_line的值傳送進去~
五、等我分析完之後,我還必在awk中透過shell打上我要打的svn指令,還好,awk提供了system(command)的這一個function,可以透過它傳送給shell指令
如何在awk使用傳送要給shell的指令
例:
awk -F: '/正規表示法/
{
cmd="命令字串";
print cmd;
system(cmd)
}' file
取得文件行數
總結了一下有五種方法:
現在有一個a文件,共有55行
第一種:
[root@host ~]# awk '{print NR}' a|tail -n1
第二種:
[root@host ~]# awk 'END{print NR}' a
第三種:
[root@host ~]# grep -n "" a|awk -F: '{print '}|tail -n1
第四種:
[root@host ~]# sed -n '$=' a
第五種:
[root@host ~]# wc -l a|awk '{print }'
第六種:
[root@host ~]# cat a |wc -l
[2009.06.14 補充]
若要一次新增許多資料的話,而且分散在各各不同的資料夾,則有三個方法,第一個是一個一個加,第二個是使用上面的script,第三個是使用下面的指令$ svn status | awk '{print $2}' | xargs svn add
而以上的指令使用條件是必需要是所有svn state所出來的檔案都是要新增的
參考資料:
好用的 awk 命令
AWK 中如何利用系統資源
怎樣取得文件行數
2008年9月6日 星期六
C++標準函式庫—STL(Standard Template Library)
何謂抽象指標(Iterator)
透過指標我們可以間接地讀取或寫入指標所指變數的內含值,指標的另一個用處是用來接受new運算子動態分配得到記憶體時所傳回的Address(然後我們再利用此指標間接操作此一動態記憶體-亦即此一記憶體沒有變數名稱「不具名物件」,所以一定要透過指標來間接操作它)。一般而言,對容器類別而言,為了達到像內建指標一樣方便的設施,我們並不是定義一個像vector<int> *pvec;這樣的指標來間接操作pvec所指到的向量,而是,我們另外定義了一個更形上更抽像的指標-叫做Iterator,此Iterator就是容器類別的指標,有了Iterator,我們可以對容器內的每一個元素做間接的讀取或寫入,更進一步來說,有了Iterator,會讓泛型演算法更加地一般化(這也是為什麼sort或copy演算法可以放諸四海皆準地用在各種容器上的原因)。每一個容器類別都有二個公開的成員函式,分別是begin()和end(),它們分別會傳回容器的第一個元素的指標(Iterator)和最後一個元素的下一個位置的指標(Iterator),如:
vector<int> ivec(10); //定義一個整數向量,內含10個元素
vector<int>::iterator iter = ivec.begin() //定義一個ivec向量的指標,它指向ivec的第一個元素
vector<int>::iterator iter_end = ivec.end() //定義一個ivec向量的指標,它指向ivec的最後元素的下一個元素
然後我們就可以利用提領(Dereference)運算子 * ,來間接地讀取或寫入第一個元素的值,如:
int ia = *iter; // 將第一個元素的內含值存入ia物件中
還有可以用遞增運算子 ++ ,將指標移到下一個或之後的其他元素當中,如:
iter++; // iter變成指向第二個元素
綜上所述,所有對內建指標可以做的提領或遞增和遞減的動作,一樣通通適用於Iterators,是不是很方便呢?
C++教學講義 Part7
2008年9月5日 星期五
qt - 透過滑鼠移動在canvas上的物件
參考資料:參考文檔的canvas example
void FigureEditor::contentsMousePressEvent(QMouseEvent* e)
{
QPoint p = inverseWorldMatrix().map(e->pos()); // 可以改成p = inverseWorldMatrix()*(e->pos());
QCanvasItemList l=canvas()->collisions(p);
for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { // Iterator請參考這裡
moving = *it;
moving_start = p;
return;
}
moving = 0;
}
QCanvasItem* moving; // 用來記錄要移動的qcanvasitem的指標
QPoint moving_start; // 用來記錄要移動的qcanvasitem的起始座標位址
這裡說明一下,it是指標性值的變數,是指到QCanvasItemList內的item的位置,所以,(*it)指的就是放在QCanvasItemList的東西,而我們這裡放的東西就是ImageItem,而ImageItem是由CanvasItem繼承過來的~ImageItem *item= (ImageItem*)(*it);,就是把基底類別(CanvasItem)的指標轉換成衍生類別(ImageItem)的指標
用到的function解釋
const QWMatrix & QCanvasView::inverseWorldMatrix () const
Returns a reference to the inverse of the canvasview's current transformation matrix.
回傳目前canvasview的反座標轉換物件的參照(reference)
QPoint QWMatrix::map ( const QPoint & p ) const
This function is obsolete. It is provided to keep old source working. We strongly advise against using it in new code.
這一個函式作廢了,請用下面運算代替
Does the same as operator *( const QPoint &)
const QPoint & QMouseEvent::pos () const
Returns the position of the mouse pointer relative to the widget that received the event.
傳回滑鼠的相對於目前widget的指標位置
QCanvasItemList QCanvas::collisions ( const QPoint & p ) const
Returns a list of canvas items that intersect with the point p. The list is ordered by z coordinates, from highest z coordinate (front-most item) to lowest z coordinate (rear-most item).
傳回所有與p點有交集的所有canvas item,且這一個list內的canvas item是由z大排到z小
QCanvas * QCanvasView::canvas () const
Returns a pointer to the canvas which the QCanvasView is currently showing.
目前qcanvasview所顯示的是某canvas,把此canvas的指標傳回
用到的類別解釋
The QCanvasItemList class is a list of QCanvasItems
QCanvasItemList is a QValueList of pointers to QCanvasItems. This class is used by some methods in QCanvas that need to return a list of canvas items.
QCanvasItemList是一連串QCanvasItem的pointer的集合,這一個class是被某一些canvas的function用來回傳一連串的QCanvasItem的pointer
延伸閱讀:
QValueList類是一個提供雙向鏈表(double-link)的基於值的模板類,也就是說是一個雙向鏈表,但是,裡面放什麼東西,還沒有定義,而QCanvasItemList就是繼承QValueList<QCanvasItem * >,也就是說雙向鏈表裡面放的是QCanvasItem的指標啦~
void FigureEditor::contentsMouseMoveEvent(QMouseEvent* e)
{
if ( moving ) {
QPoint p = inverseWorldMatrix().map(e->pos());
moving->moveBy(p.x() - moving_start.x(),p.y() - moving_start.y());
moving_start = p;
canvas()->update();
}
}
void QCanvasItem::moveBy ( double dx, double dy ) [virtual]
Moves the canvas item relative to its current position by (dx, dy).
移動canvas item對於目前的位置的相對偏移(dx,dy)
動作解析:滑鼠先移動到目的地,算出滑鼠與目前的座標差,而這個座標差就是相對於原位置的偏移~再根據這一個偏移值移動這一個canvas item
====================================================
總算完成透過滑鼠移動canvas item的程式了,
這裡要另外一說的就是,inverseWorldMatrix()只有當在設定完WorldMatrix之後,才會有效果,基本上,若沒有設定過,就不需要使用這一個function
2008年9月4日 星期四
程式設計的版本控制 - SVN - 指令大全
path:表示本機路徑
url:表示是server上的目錄
file:是本機檔案
0. 一開始要把之前完成的程式上傳到空的svn server
[root@host ~]# svn import path url
1. 將文件checkout到本機端,其中path是你要新增的資料夾是用來放置下載下來檔案;url是網路上server的位置,xxx是使用者名稱
[root@host ~]# svn checkout path url --username xxx
如果我現在有9個版本,我要取得第二個的話就打以下指令,下載第二個版本到本機目錄path下
[root@host ~]# svn checkout -r 2 url path
2. 往檔案庫中添加新的檔案或資料夾
[root@host ~]# svn add file(or path)
3. 將修改過的文件提交到檔案庫
[root@host ~]# svn commit
4. 鎖定工作複本路徑或是檔案庫的 URL, 這樣就沒有其它使用者可以對它們送交任何更動.
[root@host ~]# svn lock path
5. 解除工作複本路徑或 URL 的鎖定
[root@host ~]# svn unlock path
6. 更新到某個版本(若沒有填,則更新到最新版本);svn update如果後面沒有目錄,默認將當前目錄以及子目錄下的所有文件都更新到最新版本。
將版本庫中的文件test.php還原到版本200
[root@host ~]# svn update -r200 test.php
更新到最新版本(如果在提交的時候提示過期的話,是因為衝突,需要先update,修改文件,然後清除svn resolved,最後再提交commit)
[root@host ~]# svn update test.php
6. 查看文件或者目錄狀態(包含子目錄),只列出與server有差異的部分
[root@host ~]# svn status path
顯示文件和子目錄狀態(包含與server沒有差異的部分也全部列出來)
[root@host ~]# svn status -v path
A file_or_dir:目錄或檔案 file_or_dir 已預定要被新增至檔案庫.
M file:檔案 file 的內容已被修改.
D file_or_dir:目錄或檔案 file_or_dir 已預定要自檔案庫刪除.
X dir:目前 dir 未納入版本控制, 但是關聯到一個 Subversion 的外部定義. 欲了解更多外部定義, 請參考 the section called “外部定義”.
? file_or_dir:目錄或檔案你可以藉由 svn status 命令的 --quite (-q) 選項, 或是對父目錄設定其 svn:ignore 性質, 就不會顯示問號代碼. 想知道有哪些檔案會被忽略, 請參照 the section called “svn:ignore”.
! file_or_dir:目錄或檔案 file_or_dir 已納入版本控制之中, 但是它不是消失, 就是不完整. 如果這個檔案或目錄被非 Subversion 的命令所刪除, 就會被判定為消失. 如果是目錄的話, 如果你在取出或是更新時中斷, 那麼它就會變成不完整. 只要執行 svn update, 就可以從檔案庫重新取得目錄或檔案, 或者以 svn revert file_or_dir, 回存消失的檔案.
~ file_or_dir:目錄或檔案 file_or_dir 在檔案庫裡是一種物件, 但是實際在工作複本中又是另一種. 舉個例子, Subversion 可能在檔案庫裡有一個檔案, 但是你刪除了這個檔案, 而以原名稱建立了一個目錄, 但是都沒有使用 svn delete 或 svn add 命令來處理.
C file:file_or_dir 處於衝突的狀態. 也就是說, 在更新時, 來自伺服器的更新與工作複本中的本地更動, 有重疊的部份. 在送交更動回檔案庫之前, 你必須先解決這個這個衝突.
第一列就是顯示上面的狀態,第二列顯示工作版本號,第三和第四列顯示最後一次修改的版本號和修改人。
7. 刪除檔案或資料夾
[root@host ~]# svn delete file(or path)
8. 查看日誌,顯示這個文件的所有修改記錄,及其版本號的變化
[root@host ~]# svn log file
9. 查看文件(資料夾)詳細信息
[root@host ~]# svn info file(or path)
這一個指令也可以查詢目前本地端的版本。
10. 比較差異
將修改的文件與基礎版本比較
[root@host ~]# svn diff file(or path)
對版本m和版本n比較差異
[root@host ~]# svn diff -r m:n file(or path)
11. 將兩個版本之間的差異合併到當前文件(但是一般都會產生衝突,需要處理一下)
[root@host ~]# svn merge -r m:n path
12. SVN 幫助
[root@host ~]# svn help
[root@host ~]# svn help ci
13.顯示path目錄下的所有屬於版本庫的文件和目錄
[root@host ~]# svn listpath
14. 創建納入版本控制下的新目錄
創建納入版本控制下的新目錄(每一個以工作副本 PATH 指定的目錄,都會創建在本地端,並且加入新增調度,以待下一次的提交。)
[root@host ~]# svn mkdir path
創建版本控制的目錄(每個以URL指定的目錄,都會透過立即提交於倉庫中創建)
[root@host ~]# svn mkdir url
在這兩個情況下,所有的中間目錄都必須事先存在。
15. 恢複本地修改(恢復原始未改變的工作副本文件)(注意: 本子命令不會存取網絡,並且會解除衝突的狀況。但是它不會恢復被刪除的目錄)
[root@host ~]# svn revert path
16. svn switch (sw):更新工作副本至不同的URL。
更新你的工作副本,映射到一個新的URL,其行為跟「svn update」很像,也會將服務器上文件與本地文件合併。這是將工作副本對應到同一倉庫中某個分支或者標記的方法。url是同一個資料庫中新的資料夾
[root@host ~]# switch url [path]
改寫工作副本的URL元數據,以反映單純的URL上的改變。當倉庫的根URL變動(比如方案名或是主機名稱變動),但是工作副本仍舊對映到同一倉庫的同一目錄時使用這個命令更新工作副本與倉庫的對應關係。
[root@host ~]# switch --relocate FROM TO [path…]
17. 解決衝突(svn resolved:移除工作副本的目錄或文件的「衝突」狀態)
[root@host ~]# resolved path
注意: 本子命令不會依語法來解決衝突或是移除衝突標記;它只是移除衝突的相關文件,然後讓 PATH 可以再次提交。
18. 看別人寫的commet
使用者在svn update前應該先查出自已目前的版本號,查目前版本號的方法如下,最大的號碼即為你目前的版本號
[root@host ~]# svn status -N -v
然後在svn update後,把原本版本號到最新版本號之間的送交註解看一下。例如:原本你的工作複本版本號為13,當你修改過後要送交之前得作一次svn update,版本號跳為17,那你這時候應該要作一次看comment的指令:
[root@host ~]# svn log -r 13:17 -v
先看看別人之前改了什麼,然後你自已評估與目前你所修改的程式流程有沒有衝突,例如:別人在16版的時候把$content[_msg]變數改為 $content[_lang]變數,那麼如果你有使用$content[_msg]的話,你就應該先改好手邊的工作複本,再作svn commit。
如果你覺得看comment不夠清楚,那麼直接比較一下程式碼到底有那裡是不同
[root@host ~]# svn diff -r 16
上面的指令會比較第16版與你手邊已修改但還未送交的版本作比較,如果你只想比較單一檔案的話,指令是:
[root@host ~]# svn diff -r 16 iLovePerl.php
有時候你個人的commit周期太慢了(可能因為一個bug一直抓不出來),那你還是要在未上傳檔案庫前,經常地(至少是一天一次)觀看遠端檔案庫的版本情況,像是你的工作複本到遠端檔案庫之間的送交註解,其指令如下:
[root@host ~]# svn log -r BASE:HEAD
這樣才不會與其他人的距離差太遠,否則等你要commit時,才來調整你的程式碼,這又太慢了。
有時候,在svn所控制的專案中,你有不想作版本控制的檔案,那該這麼作呢!
像是資料庫的設定檔,這個東西,每個程設師在開發狀態時,可能用的都是臨時性的資料庫,一個人一種設定,如果每一次commit或update後都把別人用的或是自己用的給重設了,那是件很麻煩的事,所以呢,我們使用svn:ignore性質來解救我們,方法如下,後來的Config代表的是一個資料夾,是你所想忽略的檔案所在的那一個資料夾,如果你想忽略的檔案是在現在的目錄中,那就把 Config 換成 .
[root@host ~]# svn propedit svn:ignore Config
然後它會進入stdin的模式,你直接打檔名進去即可,像是
[root@host ~]# svn propedit svn:ignore Config DB.config
然後按下 Ctrl+D即可。請記住DB.config是在Config資料夾中的檔案喔,而且DB.config檔不應該送進svn add中喔
[問題]
19. 像我的話,會由之前某一個檔案copy到另一個檔案,然後,要add的時候會出現「此資料夾以在控管內」,這是因為每一個資料夾內都會有一個.svn的隱藏資料夾,而在由其它資料夾copy過來時,同時也把這一個資料夾也copy過來,這個時候只要把.svn資料刪掉就可以了~
20. 當產品要release出去時,如何把每一個資料夾下的.svn刪掉哩?
其實不是刪掉,而是透過export不會產生.svn資料夾
[root@host ~]# svn export url path (跟 checkout 參數類同)
[2014.05.13 補充]
在commit時,同時加入描述。
% svn commit --message "Corrected number of cheese slices."
[2014.05.29 補充]
方法1
用\n來當作換行
% svn ci -m "This is the first line\nThis is the second line"
方法2
直接 svn commit,然后在vim中编辑log(需要bash中提前设置$SVN_EDITOR=vim)
方法3
提交指定文件中的log
-F [--file] ARG : read log message from file ARG
[2014.06.05 補充]
Log: 如果沒輸入參數, 預設會把所有 commit log 都列出來
svn log
svn log -l 10 # 顯示 10 筆(最新 10筆 Log)
svn log -c 100 # 顯示 revision 100 的 Log
svn log -v -c 100 # 顯示 revision 100 的詳細 Log
參考資料:
svn命令
版本控制系統:svn(subversion)
Version Control with Subversion
SVN命令(linux下)
Version Control with Subversion
目前用不到資料:
研究生必備SVN版本控管
在Linux上裝SVN + Backup Script
Linux(Ubuntu)下Apache + Svn的安装初步完成
svn commit的log中输入换行符
SVN 基本指令教學
程式設計的版本控制 - SVN - 完整例子說明
今天花了一整天,總算把SVN弄的差不多了~雖然今天花很多時間,但是,我知道這個系統會替我以後寫程寫省很多時間(我猜的)~
那我們就用一個完整的簡單例子來說明吧~
環境:Linux文字模式、Google的Project Hosting
申請跟測式的步驟在程式設計的版本控制 - SVN說明的應該很清楚了~這裡我們直接用例子來說明吧~
建立一個新的project吧~我這裡的示範project是goodmorn,那當然啦~我的帳號是superporter2001
這裡先假設已經看過前一篇文章,在google的Project Hosting建立一個新的Project叫做goodmorn
我們在建立一個~/svn資料夾,並且進入這一個資料夾
[root@host ~]# mkdir svn
[root@host ~]# cd svn
將資料 checkout 回來,也就是說把google Project Hosting的goodmorn Project下載到目前目錄下的goodmorn
[root@host ~/svn]# svn checkout https://goodmorn.googlecode.com/svn/trunk/ goodmorn --username superporter2001
系統會多一個~/svn/goodmorn的資料夾
在我們寫完一個main.cpp檔案完之後,這一個檔案的目錄在~/svn/goodmorn下,我們將此檔案(目錄)新增進 svn中
[root@host ~/svn]# svn add goodmorn/main.cpp
然後,我們上傳到svn中
[root@host ~/svn]# svn commit goodmorn
耶~那這個時候大家可能會說~那我一個檔案要add一次~那我很多檔案不就要add很多次?其實不用,假設在~/svn/goodmorn/testfile/下有3個檔案a.jpg、b.jpg、c.jpg,我們只要打以下指令
[root @host ~/svn]# svn add goodmorn/testfile/
它就會把testfile下的檔案都加進去啦~
這裡有一個例子要大家注意~若我新增一個testfile2,那我要如何更新到svn server呢?有兩個方法
方法1
[root@host ~/svn/goodmorn]# mkdir testfile2
[root@host ~/svn/goodmorn]# svn add testfile2
方法2
[root@host ~/svn/goodmorn]@ svn mkdir testfile2
這裡要跟各位說的是,若有要move、copy、mkdir的話,就用svn內建的指令吧~可求助svn help
注意,當專案納入subversion的控管後,若要對專案內的檔案作刪減增加,必須都用client軟體內的對應功能來操作,否則可能會有問題。另外就是專案下的每個目錄中皆有.svn的隱藏目錄,這是subversion用來控管的目錄,請不要刪除或修改裡面的內容。
同時,我發現一個情況~我本來在其它資料夾放置我之前寫好的程式碼,我把它copy到~/svn/goodmorn,但是,確發生問題~
svn: warning: 'car-sim_1.00' is already under version control
耶~它說早就在控管中~但是,commit它確沒有上傳~找到一個強制的方法~[root@host ~/svn]# svn import car-sim_1.00 https://goodmorn.googlecode.com/svn/trunk/硬是把它上傳上去,等一下再checkout下來~就正常了~
會照成上面的原因是因為在要上傳的資料夾中,有.svn的檔案存在,所要上傳時,系統才會說因為資料夾已在控管中,決解方法是把隱藏檔.svn刪除~
[root@host ~]# find ./ -name .svn -exec rm -rfv {} \;
就可以把目前目錄下(包含子目錄)的.svn檔案全部刪除~
與svn server比較檔案差異也很好用喔~
[root@host ~/svn/goodmorn]# svn status
SVN 檔案狀態資訊:
- ?: 此檔案不存在 SVN 裡面
- A: 此次新增的檔案
- C: 此檔案已經有人改過, 合併不成功, 需要人工介入
- D: 此次移除的檔案
- M: 此檔案有修改過
- U: 此檔案有被更新過
程式設計的版本控制 - SVN
[2009.02.17] 更新
產來在判斷是否有新增資料或是修改資料時,會自動略過*.o的檔案,不過,執行檔就不會了略過
[2009.02.05]更新
google code容量變大了很多,由原來的100mb增至2048mb,單個文件也由20mb增至40mb。好high啊!!
當程式越寫越大時,這個時候就需要一個系統來控制你寫的版本~
尤其是當多個人同時在寫一個系統的時候,這個版本控制就顯得格外的重要~
概念可以參考這裡版本控制系統的基礎觀念
今天也不知道為什麼就想到版本控制的東西,這個應該就是李文雄老師說的蘊釀吧~
不過,應該會對我寫程式有很大的幫助~
所以,今天就先來研究如何使用版本控制的系統吧~
1. 先到Google的Project Hosting註冊吧~
2. 並且依用 Subversion 跟 Google Code 作版本控制 (一)建立一個新的project吧~我這裡的示範project是goodmorn,那當然啦~我的帳號是superporter2001,在這一個網址
http://code.google.com/p/XXX/source/checkout
其中XXX的部分就是專案的名稱,目前這一個例子的專案名稱是goodmorn
可以了解google提供的url
3. 在client端安裝svn client吧
[root@host ~]# apt-get install subversion subversion-tools
4. 第一次把server上的目錄下載下來,google在Source-Checkout有提示指令(這裡要注意的是,它要你輸入的密碼不是你google的密碼,而是要去左上角的Setting裡面有一組密碼哩~)
[root@host ~]# svn checkout https://goodmorn.googlecode.com/svn/trunk/ goodmorn --username superporter2001
5. 這一個時候會在目前的目錄下新增一個檔案goodmorn,然後,我們試著在goodmorn下新增一個檔案testfile.txt,並把它加入準備要上傳的schedule中
[root@host ~]# touch goodmorn/testfile.txt
[root@host ~]# svn add goodmorn/testfile.txt
6. 然後,我們準備上傳我們修改好的檔案
[root@host ~]# svn commit goodmorn
7. 噹噹~進入server後,會出現剛剛修改的檔案哩~
8. 今天再繼續研究其它參數吧~反正,有問題就打以下指令
[root@host ~]# svn help
若要查比較詳細的資料可以打以下指令,例如要查svn add
[root@host ~]# svn help add
如果我現在有9個版本,我要取得第二個的話就打以下指令
[root@host ~]# svn checkout -r 2 https://goodmorn.googlecode.com/svn/trunk/ goodmorn --username superporter2001
svn指令索引
SVN 基本功能:
Import: 將整個 project_directory 的資料 import 進 svn 裡面
- svn import project_directory http://DOMAIN/svn_project
- svn import project_directory file:///SVN_PATH/svn_project
Checkout: (checkout 可簡寫成 co), 將資料 checkout 回來
- svn co http://SVN_PATH/svn_project
- svn co file:///SVN_PATH/svn_project
- svn co -r 12 file:///var/lib/svn/dev/projects # 出第12版的 projcets code
List: (list 可簡寫成 ls), 看上面有哪些檔案/資料
- svn ls http://SVN_PATH/svn_project
- svn ls file:///SVN_PATH/svn_project
Update: (update 可簡寫成 up), 將目前資訊更新成 SVN 線上最新版本.
- SVN_CHECKOUT_DIR$ svn up
- SVN_CHECKOUT_DIR$ svn ci
- SVN_CHECKOUT_DIR$ svn st
- SVN_CHECKOUT_DIR$ svn add filename 或 svn add directory
- SVN_CHECKOUT_DIR$ svn mv filename new_filename
- SVN_CHECKOUT_DIR$ svn revert [file | directory]
SVN 檔案狀態資訊:
- ?: 此檔案不存在 SVN 裡面
- A: 此次新增的檔案
- C: 此檔案已經有人改過, 合併不成功, 需要人工介入
- D: 此次移除的檔案
- M: 此檔案有修改過
- U: 此檔案有被更新過
參考資料:
用 Subversion 跟 Google Code 作版本控制 (一)
用 Subversion 跟 Google Code 作版本控制 (二)
維基百科 - 版本控制
O'Reilly - 版本控制
版本控制系統的基礎觀念
版本控制系統(svn) - client版本
SVN基本指令教學
SVN教學
2008年9月3日 星期三
qt - canvas - 動畫播放
QCanvasSprite 可以根據一組給定的圖片進行連續的圖片播放,這組圖片是設定在QCanvasPixmapArray類別中,QCanvasPixmapArray中的圖片都是以索引來管理,我們可以使用setImage()方法來讀入圖片,我們使用setSequence()指定這組 QCanvasPixmapArray圖片給QCanvasSprite物件。
下面這個程式很簡單,示範如何使用QCanvasSprite進行動畫播放,畫面會有兩隻小毛蟲進行賽跑,不斷的一伸一縮並向右移動:
在QCanvasSprite的精神就是設定一個物件,它的顯示圖片可以變化~
這一個例子就是兩個圖片一直循環變化~
因為QCanvasSprite是繼承QCanvasItem,所以,呼叫void QCanvasItem::setVelocity ( double vx, double vy ) [virtual],可以設定它的移動速度~
main.cpp
#include <qapplication.h>
#include <qcanvas.h>
#include <qimage.h>
class Caterpillar : public QCanvasSprite {
public:
Caterpillar(QCanvas *canvas) : QCanvasSprite(0, canvas) {
static QCanvasPixmapArray ani;
ani.setImage(0, new QCanvasPixmap("cater1.jpg")); // 讀入一組圖片
ani.setImage(1, new QCanvasPixmap("cater2.jpg"));
setSequence(&ani); // setup圖片組
setFrameAnimation(QCanvasSprite::Cycle); // 循環播放
}
};
class View : public QCanvasView {
public:
View(QCanvas& canvas) : QCanvasView(&canvas){
canvas.resize(300, 200);
setFixedSize(sizeHint());
Caterpillar *cater1 = new Caterpillar(&canvas);
cater1->move(250, 50);
cater1->setVelocity(-1, 0);
cater1->setZ(10);
cater1->show();
Caterpillar *cater2 = new Caterpillar(&canvas);
cater2->move(250, 100);
cater2->setVelocity(-1.5, 0);
cater2->setZ(10);
cater2->show();
}
};
int main(int argc, char** argv) {
QApplication app(argc, argv);
QCanvas canvas(0, 0);
canvas.setAdvancePeriod(500); // 移動更新間隔,同時,每500ms會變換圖片一次
canvas.setDoubleBuffering(true); // double buffer
View c(canvas);
app.setMainWidget(&c);
c.show();
return app.exec();
}
參考資料:
QCanvas 類別 - QCanvasSprite 動畫播放
網路上的blog - 學習歷程
用來記錄網路上有人的學習歷程,以後,無聊的時候可以看哩~還在思考要如何分類~
就把每一個blog有我想要的分類放在超聯結上面吧~到時候用ctrl+F去找就好了~
史丹利部落格
B生的部落格
[賴榮樞]的軟體資訊誌
軟體工程師:謝坤龍
資訊工程師...
MrMo.cc
Embedded Linux經驗分享
工程師的網頁
大頭鰱的部落格格
某一個老師的網頁
Jing Mine Chuan(井民全)
vim
Rickey's pets
正因為活著
linux學習筆記
C/C++、PHP、Linux、Windows
記錄生活點滴及IT學習筆記
心情、雜事、好文
▁▂▃▄ⓟⓔⓣⓔⓡⓙⓐⓜⓔⓢ▄▃▂▁
C++、C、PHP、Linux、ASP
心情雜物間
PHP、雜
慢條斯理的溫柔
雜
Tsung's Blog
C++、C、PHP、ASP、Linux、雜
尺有所短,寸有所長
電腦-雜
世樺部落格
電腦-雜、C++/C、QT
擴擴咱 2.0
電腦-雜
矇矇的秘密基地
電腦-雜-8051-linux device driver-C/C++
啾啾ㄟ部落格
電腦-程式教學
Victor's程式設計教學
軟體品質
中文品質筆記
電腦-雜-linux
小惡魔 - 電腦技術 - 生活日記 - 美食介紹 - AppleBOY
電腦、旅遊、linux、雜
麥雞來福
emacs、數學、心情,筆記
炎龍的筆記本
網路
研究手記--我的研究生活
c/c++、 ANN、Dreamweaver、EP/GP、Fedora、Firefox、Fireworks、Flash、Flex、Gtk/Qt/wxWidget、Java、Perl、Short Flim、SQL、SSH/SSL、Ubuntu、Windows
#define KNOWLEDGE FREE
2008年9月2日 星期二
qt -canvas - 物件之間的碰撞
現在要開始研究如何讓canvasitem之間的物件碰撞時,會觸發碰撞的訊息~
非常好~在QT中就內建了這一個函數!
bool QCanvasItem::collidesWith ( const QCanvasItem * other ) const [pure virtual]
這一個透過上一篇文章的例子做一些修改,可以知道這一個可以正確運作無誤~
void contentsMousePressEvent(QMouseEvent *e)
{
r->move(e->pos().x(), e->pos().y());
if (r->collidesWith(p))
t->setText("Collision");
else
t->setText("That is ok!");
}
當我按滑鼠時,程式會判斷三角型與正方型是否有碰撞~
基本上應該是要讓程式自己去偵測兩物是否有碰撞,而不是我去按滑鼠後,才去偵測~
目前我知道設定完setAdvancePeriod後,時間到後會自動呼叫advance(),
基本上偵測的function應該是要放在advance()裡面~
但是,void QCanvas::advance () [virtual slot]是父類別的function,而時間到的時候呼叫的是父類別的advance(),那麼應該如何修改,才會讓它呼叫子類別另外定義的advance哩~這是我目前需要解決的問題~明天試試看,先新建一個類別繼承QCanvas,然後,重新定義advance()試試看~有點累了~回家睡覺吧~
[2008.09.3 更新]
在今天早上研究到現在總算成功的讓每30毫秒就去判斷一次物件是否有碰撞到~
話不多說~直接把程式碼貼上來吧~我覺得我的方法還蠻笨的,沒有用到物件導向的精神~
我想當我上過這一個學期的物件導向後,應該會有更深入的認知吧~
說明主要的精神:
現在有兩個類別myqcanvas、View這兩個類別,而在main.cpp設定myqcanvas的velocity後,每30ms會呼叫advance()一次。因此我另外改寫了myqcanvas的advance,這裡有用到virtual function的觀念,請參考c++ - virtual function。
本來View、myqcanvas是兩個獨立的類別,但是,為了要讓View中的兩個圖形可以在myqcanvas的advance()判斷是否有碰撞,因此,在View中設定了三個回傳指標的public function。並在myqcanvas設定一個function可以設定這三個物件的指標。
本來每30豪秒會呼叫QCanvas::advance(),但是,因為,它是virtual function,所以,當我重新宣告一個advnace()時,就算是QCanvas指標指到MyQcanvas的物件,當透過QCanvas指標呼叫advance()時,就會是呼叫我新增的advance()了,而不是QCanvas的advance()~因此,完成了這一個碰撞的目標了~
myqcanvas.h
#ifndef MYQCANVAS_H
#define MYQCANVAS_H
#include <qcanvas.h>
class MyQCanvas:public QCanvas
{
Q_OBJECT
public:
MyQCanvas(int w=0,int h=0);
void setAddress(QCanvasPolygon*,QCanvasRectangle*,QCanvasText*); // 新增的部分,設定這三個物件的指標
protected:
void advance(); // 修改父類別的virtual function
private:
QCanvasPolygon *my_p; // 新增的變數,用來記錄多角形的指標
QCanvasRectangle *my_r; // 新增的變數,用來記錄方形的指標
QCanvasText *my_t; // 新增的變數,用來記錄文字的指標
};
#endif // MYQCANVAS_H
myqcanvas.cpp
#include "myqcanvas.h"
MyQCanvas::MyQCanvas(int w,int h):QCanvas(w,h)
{
// do nothing
}
void MyQCanvas::advance() // 新增的部分
{
if (my_r->collidesWith(my_p)) // 判斷是否有發生碰撞
my_t->setText("Collision");
else
my_t->setText("There is no Collision!");
QCanvas::advance(); // 衍生類別呼叫基底類別的advance function
}
void MyQCanvas::setAddress(QCanvasPolygon* p,QCanvasRectangle* r,QCanvasText* t)
{
my_p = p;
my_r = r;
my_t = t;
}
view.h
#ifndef VIEW_H
#define VIEW_H
#include <qcanvas.h>
class View:public QCanvasView
{
Q_OBJECT
public:
View(QCanvas& canvas);
QCanvasPolygon* getPolygon() const; // 新增的function,用來傳回多角形的指標
QCanvasRectangle* getRectangle() const; // 新增的function,用來傳回方形的指標
QCanvasText* getText() const; // 新增的function,用來傳回文字的指標
protected:
void contentsMousePressEvent(QMouseEvent *e);
private:
QCanvasPolygon *p;
QCanvasRectangle *r;
QCanvasText *t;
};
#endif // VIEW_H
view.cpp
#include <qfont.h>
#include <qimage.h>
#include "view.h"
View::View(QCanvas &canvas):QCanvasView(&canvas)
{
canvas.setBackgroundPixmap(QPixmap("logo.jpg"));
canvas.resize(370,300);
setFixedSize(sizeHint());
p = new QCanvasPolygon(&canvas);
QPointArray a;
a.setPoints(3,50,100,200,200,50,200);
p->setPoints(a);
p->setBrush(Qt::blue);
p->setZ(10);
p->show();
r = new QCanvasRectangle(100,100,50,100,&canvas);
r->setVelocity(0.5,0);
r->setBrush(Qt::red);
r->setZ(10);
r->show();
t = new QCanvasText("What will you",&canvas);
t->setFont(QFont("Helvetica",12,QFont::Bold));
t->setColor(Qt::blue);
t->setZ(20);
t->setTextFlags(AlignBottom);
t->move(5,20);
t->show();
}
void View::contentsMousePressEvent(QMouseEvent *e)
{
r->move(e->pos().x(),e->pos().y());
}
QCanvasPolygon* View::getPolygon() const
{
return p;
}
QCanvasRectangle* View::getRectangle() const
{
return r;
}
QCanvasText* View::getText() const
{
return t;
}
main.cpp
#include <qapplication.h>
#include "view.h"
#include "myqcanvas.h"
int main(int argc,char** argv)
{
QApplication app(argc,argv);
MyQCanvas canvas(0,0);
View c(canvas);
canvas.setAddress(c.getPolygon(),c.getRectangle(),c.getText()); // 新增的部分
canvas.setAdvancePeriod(30);
canvas.setDoubleBuffering(true);
app.setMainWidget(&c);
c.show();
return app.exec();
}
參考資料:回傳指標資料範例
qt - canvas
除了使用QPainter相關類別來進行簡單的繪圖之外,我們還可以使用Qt所提供的繪圖模組QCanvas,每一個QCanvas繪圖都是一個物件,可以分別為它們設定位置與深度,也可以設定移動速度,在製作動畫上相當的方便。
在繪圖時,我們準備一個QCanvas物件,它就像是一塊畫布,我們在這塊畫布上畫上QCanvasItem物件,是否顯示一個QCanvasItem物件可以使用show()方法來控制,而觀看繪圖結果時是使用QCanvasView物件。
在程式撰寫上,我們繼承QCanvasView類別,將QCanvas傳遞給它,然後定義每個QCanvasItem繪圖方法;我們將這個QCanvasView類別當作Qt的主Widget,就可以顯示在視窗上。
下面這個程式是個簡單的示範,畫面中的長方形會不斷的往右移動,您可以使用滑鼠將之設定回來,而由於我們設定了深度,所以長方形會一直被三角形所覆蓋:
main.cpp
#include <qapplication.h>
#include <qcanvas.h>
#include <qfont.h>
#include <qimage.h>
class View : public QCanvasView {
public:
View(QCanvas& canvas) : QCanvasView(&canvas){
canvas.setBackgroundPixmap(QPixmap("logo.jpg"));
canvas.resize(370, 300);
setFixedSize(sizeHint());
p = new QCanvasPolygon(&canvas); // 多邊形
QPointArray a;
a.setPoints(3, 50, 100, 200, 200, 50, 200); // 意思是共有3個點分別為(30,100)、(200,200)、(50,200)
p->setPoints(a);
p->setBrush(Qt::blue);
p->setZ(10); // 深度
p->show(); // 顯示繪圖物件
r = new QCanvasRectangle(100, 100, 50, 100, &canvas); // 四方形
r->setVelocity(0.5, 0); // 移動速度
r->setBrush(Qt::red);
r->setZ(10);
r->show();
t = new QCanvasText("What will you study today? ^o^", &canvas); // 文字
t->setFont(QFont("Helvetica", 12, QFont::Bold));
t->setColor(Qt::blue);
t->setZ(20);
t->setTextFlags(AlignBottom);
t->move(5, 20);
t->show();
}
protected:
void contentsMousePressEvent(QMouseEvent *e) {
r->move(e->pos().x(), e->pos().y());
}
private:
QCanvasPolygon *p;
QCanvasRectangle *r;
QCanvasText *t;
};
int main(int argc, char** argv) {
QApplication app(argc, argv);
QCanvas canvas(0, 0);
canvas.setAdvancePeriod(30); // 移動更新間隔:
canvas.setDoubleBuffering(true); // double buffer
View c(canvas);
app.setMainWidget(&c);
c.show();
return app.exec();
}
QCanvas的畫面更新是由setAdvancePeriod()來控制,配合QCanvasItem的setVelocity()方法,就可以製作出移動的效果,下圖為執行的結果畫面:
virtual void advance ( int phase )
當phase是1時,QCanvasItem就依速率在移動;當phase是0時,QCanvasItem就算有設速率,一樣不會有動作。
參考資料:Qt3 Gossip: QCanvas 類別 - 簡單深度與移動設定
延伸閱讀:
Canvas Example
Qt開發雜記(三)
如何辦認電容的好壞
老弟傳來訊息說因為LCD換了新的電容,可以不用整個LCD都換掉,省了一筆錢哩~
消費者不可不知的權利
國內有些公司(如華碩,技嘉等等)針對生產品皆有免費換電容服務
不論保固期與否,如有電容目視如上文所述之(A級明顯不良品.或B級不良品)免費更換電容不收取任何檢測費及任何零件費
即使不清楚是否故障與否之產品若有明顯不良品之電容問題,也可送回更換
更換完畢將例行性測試產品功能是否正常
如果更換電容尚有其他故障將再次報價(顧客也可不付任何費用取回)
介紹主角-電解質電容
電路板上會有一些圓柱體,側面膠皮也並標示了以uF和V為單位物體
(例:常見的有3300uF6.3V)
參考資料:富大電腦工作室
2008年9月1日 星期一
QT - 建立一個空心圓
修改example08的
cannon.cpp
void CannonField::paintEvent( QPaintEvent * )
{
QPainter p( this );
p.setBrush( NoBrush );
p.setPen( red ); // 讓圖的外圍為紅色畫的
p.drawEllipse(0,0,120,120);
s = "Angle = " + QString::number(ang);
p.setPen( SolidLine );
p.drawText(rect(),AlignCenter,s);
}明天任務:畫出一個有顏色的空心圓畫出來啦~就在原程式改一下就好啦~結果在上面啦~
測出來的結果就算是空心圓,實際上其實不是~只是空心的部分沒有畫出來而以。基本上還是要用Canvas來畫會比較好~而且基本上Canvas本身就使用雙緩沖哩~另外,可以根據需要更新的部分去更新就好哩,不會整個都刪掉再重畫哩~
計算機網路實驗 - 以NS2模擬工具實作
這是我今天看了這一本書的大綱:
NS2是一套物件導向的網路模擬器,由UC Berkeley完成,具有模擬真實系統的架構和特性
網路架構:模擬router、link、end-point
網路特性:packet delay、packet drop
第二章:TCL語法
可以參考這裡~作者的網站
第三章:
TCP與UDP模擬實驗
呈現網路效能、評比指標:
1. End-to-End Delay
2. Jitter - 兩個封包傳送的延遲時間的差異
3. Packet Loss
4. Throughput
在NS2中,我們都透過awk去分析出來的報表
第四章:亂數產生器(Random Number Generator)
如何產生合乎現實的例子
NS2提供Pareto、Constant、Uniform、Exponential、HyperExponential
第五章:信賴區間(Confidence Interval)
這裡是說明什麼是信賴區間,這一個在網路上找有一堆資料
1. 母群體(population):為特定研究的所有元素所組成的集合
2. 樣本(sample):母群體的部分集合
3. 母群體平均數(population mean)
4. 樣本平均數(sample mean)
5. 變異數(variance)
6. 樣本變異數(sample variance):由母群體取出一部分樣本的變異數
7. 母群體標準差(standard deviation)
8. 樣本標準差(sample standard deviation)
9. 信賴區間(confidence interval)
求得一個機率範圍(probability bound)使母群體平均有很高的機率能在上限c1與下限c2的範圍內
(1). 信賴區間
(2). 顯著水準
中央極限定理 (Central Limit Theorem)
商用統計學
第六章:佇列管理機制
被動式佇列:DropTail
基於路由器的RED和Droptail算法比較
佇列管理演算法
主動式佇列:RED(Random Early Detection)
主動式會在佇列滿之前就把封包丟棄。
第七章:路由(Dynamic Routing)
靜態路由(static route):由網管人員手動輸入。優點:頻寬都用在傳送資料;缺點:路由器不會主動發現新的router
動能路由(dynamic route):根據協定(routing protocol)或演算法來動態維護路由表中的內容。優點:router彼此交換訊息不用手動維護routing table。缺點:需要消耗網路的頻寬。
預設路由(default router):預設路由是當router無法判斷IP封包轉送的路徑時,就會將封包送往一個預設的閘道器(default gateway)
在決定router table時,會依到達目地的時的成本來考量,這裡的成本可以是hop count、propagation delay、load、bandwidth、reliability
第八章:TCP提供reliable傳輸服務具flow control、congestion control
第十一章:同步化現象(TCP Global Synchronization)
由於網路上的TCP Connection可能會在不同的時間啟動,因此當一個新的TCP Connection進入網路時,在這一個時間點上,它的Congestion window (cwnd)和其它的TCP Connect的cwnd大小可能是不同的,那麼這一些TCP Connection要怎麼公平地競爭頻寬呢?
第十二章:影響TCP效能的幾個因素
1. Round-Trip (RTT):當同時有多個TCP Connection共同相同的Link時,由於RTT較短的Connection等待ACK開啟Congestion window的時間較短,因此和RTT時間較長的TCP Connection比較起來,資料傳輸的效能會比較好。
2. Timer Granulariy:一般而言,通常TCP在實際運作時,並不會真的隨時去注意封包是否過期,而是設定一個時間值,稱為"Coarse-grain timer",每隔一段時間才去檢查是否有封包已經Timeout了。因此,當有封包遺失時,這意謂著一個封包從遺失到直到timeout被重送的時間也會大大的增長。
3. Slow-start threshold:ssthresh的值決定終止slow-start、開始進入Congestion avoidance時window的大小。若設的太小,會使得TCP因為太早進入Congestion avoidance階段,而使得頻寬的使用率變的很差。
4. 封包大小、網路的佇列管理機制、有線/無線的環境。
第十五章:資料流整形器 (Traffic Shaper)
1. 漏桶演算法 (leaky bucket algorithm)
2. 令牌桶演算法 (token bucket algorithm)