about 4 years ago

通常而言,C程式的記憶體堆疊可以分成以下幾類:

  1. Text segment
  2. Initialized data segment
  3. Uninitialized data segment
  4. Stack
  5. Heap

示意圖:


(from http://www.geeksforgeeks.org/memory-layout-of-c-program/)

[Text Segment]

  1. Code Segment,包含程式碼以及可以執行的指令
  2. 放在Memory中low level address的位置,避免被stack/heap overwrite
  3. 此區塊通常是shareable,比如說同時存在相同的Process時,只會共用一份text
  4. Read-only,避免程式自己修改自己的Instruction

[Initialized Data Segment]

  1. 包含由Programmer自己定義的Global Variable/Static Variable
  2. 可以再細分為Read-Only和Read-Write Segment

    (global) int a = 1; //Read-Write

    const int a = 1; //Read-Only

[Uninitialized Data Segment]

  1. A.K.A BSS segment
  2. 包含所有宣告為global/static的變數中,沒有任何初始值,或是初始值為0的變數

    static int i; //BSS segment

    static int j = 0; //BSS segment

[Stack]

  1. 存放"Automatic Variables",比方說function內的local variable
  2. 記錄function的堆疊狀況,比如caller的address,讓function結束後可以順利return。每個function都有自己的堆疊空間,不同function的變數不會互相干擾

[Heap]

  1. 可配置的動態記憶體空間,通常使用malloc/realloc/free函式

    p1 = (char *)malloc(10);
    根據以上的程式碼,會在Heap分配一塊10byte的空間。但是p1仍然是在Stack中,存放剛剛分配出來的空間的位置。

  2. 當Heap跟Stack的pointer collision,就會 Out Of Memory

  3. All threads share a common Heap.每個thread都有自己的stack,但是Heap是共用的

關於Initialized Data Segment & BSS Segment的小小DEMO

mem_survey.c
#include <stdio.h>
static int x;//not initial static data
static int y;//not initial static data
int main()
{
    return 0;
}

guang@ubuntu:~/Documents/C$ gcc mem_survey.c
使用size來觀察section分配的狀況
guang@ubuntu:~/Documents/C$ size a.out
結果:

text data bss dec hex filename
1117 552  16 1685 695 a.out

現在將x賦予初始值

mem_survey.c
#include <stdio.h>
static int x=1;//give a intial value
static int y;//not initial static data
int main()
{
    return 0;
}

來看看會有什麼改變
guang@ubuntu:~/Documents/C$ size a.out
結果:

text data bss dec hex filename
1117 556    12 1685 695 a.out

可以發現bss從16->12,data從552->556

Reference
http://kirenenko-tw.blogspot.tw/2012/07/heap-and-stack.html
http://www.geeksforgeeks.org/memory-layout-of-c-program/
http://en.wikipedia.org/wiki/Data_segment
http://stackoverflow.com/questions/1665419/do-threads-have-a-distinct-heap

 
about 4 years ago

簡單來說,可以將程式的權限在runtime提升成該程式的擁有者.

下面是一隻簡單的示範程式

get_euid.c
#include <stdio.h>
int main()
{
        printf("You're euid is %d\n",geteuid());
}

編譯
gcc -o get_euid get_euid.c
先看看目前的權限

get_euid的擁有者是guang,屬性是-rwxrwxr-x

現在將user換成root
su root
執行get_euid
./get_euid


結果是0,表示是以root身分執行

那現在切入正題,來設定euid
先切回guang
chmod 4775 get_euid


可以發現get_euid的權限已經變成-rwsrwxr-x

再換成root身分
執行get_euid
./get_euid


執行的身分變成了1000(guang的uid) 而不是原本的0(root的uid)

 
about 4 years ago

Mosquitto 是Open Source的MQTT Broker

此篇筆記主要是記錄如何安裝並使用Mosquitto

下載

http://mosquitto.org/download/
選擇自己的OS,這裡將以win7為例 (mosquitto-1.3.2-install-win32.exe)

安裝

Follow Installer,基本上就一路按下一步
安裝完成後,目錄會放在
C:\Program Files(x86)\mosquitto
並且會新增環境變數
MOSQUITTO_DIR指到該目錄

操作

Broker的主程式為mosquitto.exe
操作方法為
mosquitto.exe -v -p port
我會習慣下-v來啟動verbose mode,方便作debug
default port是1883


到這邊為止,已經成功跑起一個MQTT Broker!

另外,在Mosquitto的目錄下還提供了publish/subscribe的程式,可以拿來玩一玩
publish:
mosquitto_pub.exe -h host -p port -q qos -t topic -m message
subscribe:
mosquitto_sub.exe -h host -p port -q qos -t topic

DEMO

1.啟動Broker
2.Subscriber 註冊感興趣的Topic(ex. sensor/temperature)


3.Publisher 發布該Topic的訊息

4.Sbscriber 接收Topic訊息

 
about 4 years ago

記錄一下快捷鍵

Create New Window ctrl + a + C

Kill Window ctrl + a + K

Next Window ctrl + a + n

Detach ctrl + a + d

List All Window ctrl + a + "

Rename Window ctrl + a + A

ReAttach screen -R

順便記錄一下目前的screen設定檔

.screenrc
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
altscreen on # erase screen when quit apps
defutf8 on
defc1 off # treat input chars 128 ~ 159 as control functions
defflow on
startup_message off
shell $SHELL
defencoding utf8
bindkey "^b"  encoding big5 utf8
bindkey "^u"  encoding utf8 big5
defbce on # erase background with current bg color
shelltitle "--"
cjkwidth on
caption always "%{WK}%-w%<%{=B GK}%n %t%{= KW}%+w%-09="
hardstatus alwayslastline "%{R}[ %{w}%1` %{R}]%=%{M}%e %{G}%H %{Y} %c %{R} %d/%m/%Y %{K} Load: %l %{w}"
screen -t screen0        0
screen -t screen1        1
screen -t screen2        2
screen -t screen3        3
screen -t screen4        4
screen -t screen5        5
bindkey \033[D prev
bindkey \033[C next
bindkey "^[[1;5D" prev
bindkey "^[[1;5C" next
#for mac
bindkey "^[[1;2D" prev
bindkey "^[[1;2C" next
 
about 4 years ago

在使用Java進行multithreading programming時,常常會想要用
thread.stop()
來結束掉一個thread
但是好景不常,stop早就已經被deprecated啦,請勿再用!
原因是因為當呼叫stop()時,thread被結束掉的地方是無法預期的,可能會造成資料的不一致
那該如何是好?
每個人可能都有自己習慣的做法,我的做法通常都是 Shared Variable搭配interrupt()

  1. Shared Variable
    在run()中利用判斷變數來決定是否該結束自己,簡單的範例程式如下

    Thread th = new Thread() 
    {
        public void run() {
        while(!isStopped){
            //do something...
    
         }
        }
    }
    

    基本上就是利用一個isStopped的變數來控制thread的生殺大權

  2. Interrupt
    那如果thread被block在IO或是Selector時該怎辦?
    因為被block時並沒辦法做check variable的動作,這時候就要靠
    thread.interrupt()
    interrupt()並不會去結束一個thread,而是丟出InterruptedException或是ClosedByInterruptionException
    這時候再到catch中把thread給結束掉

    public void run() {
        while(true) {
         try {
             Thread.sleep(Long.MAX_VALUE);
         } catch (InterruptedException exit) {
             break; //Break out of the loop; ending thread
    
         }
     }
    }
    

別想用外力強迫Thread結束,應該用緩和的方式讓它慢慢死去...

Reference.
[1]http://10kloc.wordpress.com/2013/03/03/java-multithreading-steeplechase-stopping-threads/
[2]https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop+to+terminate+threads()
[3]http://funkie921.blogspot.tw/2009/04/interruptthread.html

 
over 4 years ago

自從投入到MAC的懷抱之後,有很多東西都要重新學習XD

在這邊記錄一下如何啟用內建的Apache server與設定php.

[設定Apache]

啟用Apache

sudo apachectl start

關閉Apache

sudo apachectl stop

重新啟動Apache

sudo apachectl restart

啟用Apache之後,在網址列直接輸入http://localhost 應該就可以看到兩個大大的字

It works!

[設定目錄]

預設的目錄是屬於系統層級的,根目錄在

Library/WebServer/Documents/

如果要建立使用者的目錄,我的做法是在家目錄底下建立一個Sites資料夾

mkdir YourUserName/Sites

接著去設定apache,建立username.conf

sudo vi /etc/apache2/users/YourUserName.conf

內容如下:

<Directory "/Users/YourUserName/Sites/">  
Options Indexes MultiViews  
AllowOverride All  
Order allow,deny  
Allow from all  
</Directory>  

接著更改權限到755 (原本預設應該是-rw-r--r--  644)

sudo chmod 755 /etc/apache2/users/YourUserName.conf

最後在重新啟動apache就可以囉!

直接在網址輸入 http://localhost/~YourUserName

[設定PHP]

儘管OS X已經預裝php,但還是需要設定一下才可以在Apache載入

sudo vi /etc/apache2/users/httpd.conf

在裡面找到

#LoadModule php5_module libexec/apache2/libphp5.so

把前面的#的註解刪掉

存檔後重新啟動apache,應該就可以啦!

最後備註一下,php.ini預設是放在etc/下面,但是實際上似乎不存在,只有php.ini.default

所以若是要自己修改php.ini,要先複製一份

sudo cp etc/php.ini.default etc/php.ini

再修改php.ini的設定就行了

 
over 4 years ago

最近在使用function array時碰到了一個問題,就是如果需要傳遞變數時,會有變數參考錯誤的

情況。其實這情況滿常見的,在bind event時也會常常碰到類似的狀況.

詳細解法可以參考:http://stackoverflow.com/questions/3495679/passing-parameters-in-javascript-onclick-event

假如說今天想要在FA這個array中塞10個function如下

function()  
{  
 alert(1);  
}  
function()  
{  
 alert(2);  
}  
function()  
{  
 alert(3);  
}  
....以此類推  

原本的寫法是:

var FA=[];  
for(var i=0;i<=10;i++)  
{  
 FA.push(function()  
 {  
 alert(i);  
 });  
}  
FA[0]();//呼叫第一個function  

結果得到的結果是  11

沒錯,因為他會reference到目前i的值,事情沒有那麼單純(是我太遜了...)

要改成

for(var i=0;i<=10;i++)  
{  
 FA.push(function(x)  
 {  
        return function()  
        {  
            alert(x);     
        }  
 }(i));  
}  

感覺有很多function的使用方法還不太熟,下次來好好研究一下匿名函式!!

 
over 4 years ago

當shell script寫好之後

可以透過

sh filename.sh  

或是

source filename.sh  

來運行

但不才小弟最近才知道這兩個的不同...囧

查了一下stackoverflow,得到一個不錯的答案 http://stackoverflow.com/a/13786536

source: 將script運行到現有的bash process

sh:folk新的sub process來運行script,所以變數在執行完後就會被drop掉

舉個例子

test.sh
#!/bin/sh  

STR="Hello World"  
echo $STR  

透過 sh

sh test.sh  
Hello World  
echo $STR  

因為變數只存在sub process中,跑完就掰了

透過 source

source test.sh  
Hello World  
echo $STR  

Hello World 因為是直接將script插入到目前的bash,所以變數還在

所以說,如果要透過shell script來設定變數,記得要用source來跑,才能繼續在原本的bash中使用設定好的變數!

 
over 4 years ago

最近剛好有機會接觸到OpenDDS

上網做功課時發現中文的資料很少

所以決定記錄在這上面啦

進入正文!

OpenDDS是以C++進行實作,但由於專案的需要,必須使用JNI的方式從Java來呼叫API

所以這邊是提供For Java的安裝方式

主要的安裝流程可以參考在DDS/java/INSTALL這份文件

而我的環境是Ubuntu14

第一步:

安裝必要的套件

  1. JDK:去官網抓

  2. GNU g++, Make:應該已經內建了,如果沒有下個apt-get install安裝一下

  3. Perl:同上

  4. ACE ORB(TAO):http://download.ociweb.com/TAO-1.6a 主程式及Patch都要抓,

抓下來後解安裝到跟DDS同一層目錄下(ACE_wrappers)

第二步:

Building DDS and Java Bindings

  1. 設定環境變數:

由於每次要使用OpenDDS時都需要export一次環境變數,所以我將它弄成shell script

filename: export.sh  
  
    #!bin/bash  
    export ACE_ROOT=/home/user/ACE_wrappers  
    export TAO_ROOT=$ACE_ROOT/TAO  
    export MPC_ROOT=$ACE_ROOT/MPC  
    export DDS_ROOT=/home/user/DDS  
    export PATH=$ACE_ROOT/bin:$DDS_ROOT/bin:$PATH  
    export LD_LIBRARY_PATH=$ACE_ROOT/lib:$DDS_ROOT/lib:$LD_LIBRARY_PATH  
    export JAVA_HOME=/usr/lib/jvm/java-7-oracle  
    export JAVA_PLATFORM=linux  
    echo FINISH  
Ps. user要換成自己的username 執行方式:  
    source ./export.sh  
  1. 設定TAO

2.1 建立 $ACE_ROOT/include/makeinclude/platform_macros.GNU

內容如下

include $(ACE_ROOT)/include/makeinclude/platform_linux.GNU  
java=1  

2.2 建立 $ACE_ROOT/bin/MakeProjectCreator/config/default.features

內容如下

java=1  

2.3 建立$ACE_ROOT/ace/config.h

內容如下

#include "ace/config-linux.h"  
  1. Build TAO Core

    基本上就是照著做就可以囉

    cd $ACE_ROOT/ace  
    make ACE  
    cd $ACE_ROOT/apps/gperf/src  
    make  
    cd $TAO_ROOT/TAO_IDL  
    make  
    cd $TAO_ROOT/tao  
    make  
    cd $TAO_ROOT/orbsvcs/orbsvcs  
    make Svc_Utils 
    

    PS. 當時在make ACE時,有一個DEV.....Reactor.cpp一直compile不過,後來上網查了資料,發現OpenDDS似乎不會用到這個,於是就去MAKEFILE.ACE中將相關的compile指令刪除,就OK了!

  2. Build OpenDDS C++ lib

    cd $DDS_ROOT/dds  
    make  
    
  3. Build the OpenDDS Java Bindings

    cd $DDS_ROOT/java  
    make  
    
  4. 基本上如果沒遇到error等程咬金,應該已經將OpenDDS整個setup起來了!

    可以用以下方式來進行check

    cd $DDS_ROOT/java/tests/multirepo  
    ./run_test.pl  
    

    如果看到 "test PASSED."

恭喜你!你已經成功建置完成啦

 
over 4 years ago

隨著年紀的增長,記憶力不斷的下降...

是時候找個地方記錄記錄了

 Time to log down!