2013年5月9日 星期四

[C]結構內動態陣列大小設初值

參考:
http://stackoverflow.com/questions/1558025/c-initialize-array-within-structure

不是後來才用malloc的那種動態陣列。

typedef struct {
  int row;
  int col;
  char **ar;
}fooStruct;

static const foostruct fooArr[] = {
  {2, 10, (char*[2]) { (char[10]) {"hello"}, (char[10]) {"world"} } },
  .....
}

這樣宣告的話

fooArr[0].ar[0]就是hello
fooArr[0].ar[1]就是world

2013年5月7日 星期二

[Socket]server程式碰上TIME_WAIT的解法

參考:
http://stackoverflow.com/questions/587961/whats-the-difference-between-time-wait-assassination-and-so-reuseaddr
http://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option-linux

有時候server程式在需要重啟的時候,(像是重新讀設定檔)
會發現即使把程式結束,再開卻失敗的情況。

在這時候用netstat -al可以觀察到,server用的某些port正處於TIME_WAIT的情況,
並要持續一段時間才會自動消失(1~4分鐘都有可能)。
而在TIME_WAIT的這些port都是無法再利用,所以才會重啟失敗。

解決辦法就是在socket做bind之前,
做setsockopt的SO_REUSEADDR:

int i=1; 
setsockopt(iSock,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));

這樣的設定就是允許另一個socket bind在TIME_WAIT的port。
但是如果該port不是在TIME_WAIT而是其他使用中狀況,bind仍會失敗。

TIME_WAIT是TCP連線的正常狀態,
代表"可能還有未傳來的資料"。

2013年3月14日 星期四

[Linux]嵌入式系統強制進入/恢復法

BusyBox v1.10.4 / U-boot

開機後等"Hit any key to stop autoboot:"訊息出現後按任何鍵停止。
這時可用"?"來確認可用指令,首先printenv確認自己的原設定。
用setenv更改bootargs,在原指令的最後面加上init=/bin/sh (或是/bin/bash)。
然後boot重開。 (不用擔心亂改,只要不save的話下次會自動還原)

這時候就可以跳過登入程序,形同root進入系統。
做原本正常開機會失敗的事,像是改密碼。

這時候若要存取其他裝置(mount相關):
先手動掛上proc:
mount -t proc proc /proc

若是在mknod之前發現自己系統是squashfs的readonly的話:

用tmpfs就可以掛出一塊記憶體空間(RAM DISK)來用:
mount -t tmpfs,size=20m /tmp         (路徑和大小任選)
如果/etc/fstab因為某原因不存在而且無法自己開一個的話:
mount -t tmpfs -o size=20m none /tmp

mknod的方法:

mknod /tmp/mtdblock3 b 31 3
mount -t jffs2 /tmp/mtdblock3 /tmp/mtdbk

如此便可在/tmp/mtdbk(路徑自選)存取mtdblock3的內容。

註:
比較重要的檔,就像是/etc/rcS.d (這名字可能不一樣,看開機去讀哪)
然後上面會呼叫/etc/rc.local
最後是/etc/fstab的分割表

利用上面的強制進入系統後,在執行/etc/rcS.d就跟一般開機流程差不多了。

2013年3月1日 星期五

[Linux]在/etc/rc.local內加入開機執行的背景程式

參考資料:
http://serverfault.com/questions/9563/bash-code-in-rc-local-not-excuting-after-bootup
http://unix.stackexchange.com/questions/14993/how-do-i-start-my-service-at-boot-time
http://www.linuxmisc.com/27-openbsd/1383bfded6bcc0f0.htm

若是發現開機程序跑完,登入後沒看到程式出現,可以做下列循序檢查:

1.先檢查rc.local是不是真的有跑,加一行簡單程式像是echo或是touch或mkdir。
2.背景程式要是要花很多時間啟動,有些script可能會停止花太長時間的程式。
3.登入後在sh下執行 /bin/sh /etc/rc.local 跑完看背景程式有沒有出來。
(我卡在這裡,開機時有程式啟動成功訊息,但登入後程序消失,在sh下跑rc.local就有活著)
4.檢查錯誤訊息如/var/log/messages
5.檢查script內有沒有用一些環境變數如$PATH,在sh下正常,但rc.local下可能不同。

可以自己寫小程式,內含sleep一段時間/啟動和結束訊息,然後在rc.local下實驗:
/usr/bin/foo &
開機時和有沒有正常啟動,登入後ps看有沒有活著。

目前查的結果"應該"就是rc.local結束後會砍child process,
導致利用"&"以及傳統fork方式做背景執行的程式被砍。
最快的解法就是執行時前面加nohup。
nohup /usr/bin/foo &
(這方法沒實驗,因為我是在精簡系統上,居然沒nohup可以用...)

這次採用的方式是利用程式內加入daemon()達成背景執行(man daemon),
利用這個函式之後就可以活過rc.local結束了。

2013年2月27日 星期三

[Linux]記憶體消失?

參考資料:
http://www.linuxatemyram.com/

free指令可以了解目前記憶體使用的狀況。
突然有一天你發現自己可用(顯示為free)的記憶體突然變得很少,
但是又沒有真的在跑很多程式,你懷疑是不是linux吃掉你的記憶體?

並不是,簡單來講,linux覺得與其讓RAM放著沒事幹,
不如讓它做點其他工作,像是檔案的buff和cache,提升系統效能。
你在其他欄位(buffers和cached)就可以發現它們跑到那邊去了。
當你真的要用更多記憶體的時候,它們會馬上回來,不需要擔心。

利用 echo 1 > /proc/sys/vm/drop_caches
就可以看到free的記憶體又變很多了。

參考資料下面也有驗證:
http://www.linuxatemyram.com/play.html

簡單來講,自己寫一個瘋狂malloc的程式,
就可以看出其實可用的記憶體仍然超過free顯示的量,
證明你還是有很多可用的記憶體,雖然它們不在free那區。

[Linux]記憶體管理(/proc/sys/vm/)

參考資料
http://www.kernel.org/doc/Documentation/sysctl/vm.txt

(註:用free指令可以看目前的記憶體使用狀況)

幾個比較有用的:
(用cat查值;用echo > 寫值,例:echo 2 > /proc/sys/vm/overcommit_memory)


drop_caches:
利用echo寫入,就可以讓linux放掉cache,讓free記憶體變多。
這操作是無害的,不會放掉髒資料(暫存卻還未寫入)。
可以在操作前先做sync寫入髒資料,這樣釋放的記憶體就會比較多。

min_free_kbytes:
設定最少必須保留多少kb的free記憶體。
不要設低於1024,不然很可能會有問題。
但設太高的話,系統就容易OOM(記憶體用光)。

overcommit_memory:
可能的值有0,1,2,預設為0。
0的話系統即使在程式要求梢多於可用記憶體時也會接受,想辦法從其他地方擠出來給你用。
(這就是overcommit)
1的話程式的記憶體要求永遠不會被拒絕。
2的話相對就是保守,超過的要求就會被拒絕。(和overcommit_ratio搭配使用)

overcommit_ratio:
當overcommit_memory被設成2,就會參考這邊的值。
這時使用者程式可用的記憶體就是swap+(實體記憶體*overcommit_ratio%)

vfs_cache_pressure:
系統取回cache的傾向,預設為100。
越低的話系統越不會放掉cache,最小為0,就永遠不放,一下就會OOM了。
反之高則沒有極限的樣子,
http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/2.6.7/2.6.7-mm1/broken-out/vfs-shrinkage-tuning.patch
甚至可以設到10萬。



一般使用者沒什麼必要去調這些就是了...
除非是在資源很少的機器上,或是高負載會碰到OOM的情況再來看這邊調整就好。

真的要詳細了解記憶體的話
Understanding the Linux Virtual Memory Manager
http://kernel.org/doc/gorman/
可以直接下載,深度了解linux的記憶體機制。(很硬...)