發表文章

目前顯示的是 2016的文章

Write FD set 的用途

一段時間,我其實都不知道 select 和 epoll 這一類 function 裏面的 writefds 到底有什麼用。read fd set很容易理解,那就是有東西要讀,或者白話一點,收到封包了。那 write fd set 到底要幹嘛呢?直到今天遇到了一個情境我才使用了它 ...

在寫 TCP socket 程式的時候,會使用到 connect 這個函式。一般來說, connect 這個函式是 blocking 的,也就是會一直到事情做完才會返回。但如果將 socket 設定成 non-blocking 模式呢?這時候 connect 會立刻返回並將 error no 設定為 EINPROGRESS。下面是"男人"的解釋:

EINPROGRESS
              The  socket  is  nonblocking and the connection cannot be completed immediately. It is possible to select(2) or poll(2) for completion by  selecting  the  socket  for  writing.   After select(2) indicates writability, use getsockopt(2) to read  the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully  (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual  error codes listed here, explaining the reason for the failure).


好了,這時候我們可以看到 select 可以用來判斷 connect 是否完成。範例程式碼如下:

#include // for printf() and fprintf() #include // for socket(), connect(), send(), and recv() #include // for so…

如何透過 Python 來呼叫 ioctl

首先,先來抄一段 wikipedia 的定義:

In computing, ioctl (an abbreviation of input/output control) is a system call for device-specific input/output operations and other operations which cannot be expressed by regular system calls. It takes a parameter specifying a request code; the effect of a call depends completely on the request code. Request codes are often device-specific.

簡單來說,ioctl 是針對 device 去做輸入輸出(白話一點,get/set)操作的一種方式,在 Linux 底下,所有的 kernel module 都可以被視做是一個 device,所以把 ioctl 當作一種 UK 的溝通機制也未嘗不可。不過如果要傳大量資料的話還是採用其他的方式比較妥當,像是 netlink。在溝通的時候,User Space 和 Kernel Space 必須先定義好雙方溝通的格式。最常見的範例基本上就是 ifconfig 這隻程式了,在這裡也不去看它,反正是一支很簡單的 C 程式。

本篇要紀錄的是,在 Python 裡要怎麼呼叫 ioctl。範例很簡單,,就是實作一支類似 ifconfig 的程式(不過只有 get,懶得寫 set)。直接放在下面:


#!/usr/bin/pythonimport socket import fcntl import sys import struct import array defget_if_list(): try: fd = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) # #define SIOCGIFCONF 0x8912 /* get iface list */ max_poss…

靈修分享:看見神

身為一個基督徒,有幾個問題幾乎是一定會被問到的。其中有一個問題幾乎一定會名列前茅的,就是「真的有上帝嗎?你讓我看見上帝,我就會信了!」在這個 Seeing is believing 的年代,事事都要講求證據以及符合邏輯的推論,如果沒見過上帝,又怎麼能信呢?無怪乎哲學家羅素說:「如果真的有上帝,那我會責備上帝怎麼不多提供自己存在的證據。」對我來說,「神既然是創造者,為什麼要合乎人的邏輯、定理?」將上帝擺在人的理性和慾望之下才是有問題的。不過有趣的地方在於,不要說是非基督徒,就是基督徒也常常對上帝提出同樣的要求:「主啊,我想要看見祢!」對基督徒來說,當在提這樣的要求的時候,似乎表示看見神就能夠更加的堅定信心,繼續面對前方的挑戰。可是,似乎神都沒有顯現,即便是對這群屬祂的百姓。為什麼不呢?如果說非基督徒是信心不夠,那基督徒呢?(當然也不是不能繼續宣稱信心不夠啦)。所以我想整理一下,到底聖經是怎麼說「看見神」這件事情。

首先從舊約開始。第一個看見神的人毫無疑問的是亞當。上帝創造亞當,並賜給他一個配偶夏娃,吩咐他們要管理看守伊甸園。他們在園中是何等的舒服,也能面對神、與神談話。直到他們聽了蛇的建議,吃了神不許他們吃的果子。

創3:7-10 他們二人的眼睛就明亮了,才知道自己是赤身露體,便拿無花果樹的葉子為自己編作裙子。天起了涼風,耶和華 神在園中行走。那人和他妻子聽見 神的聲音,就藏在園裡的樹木中,躲避耶和華 神的面。耶和華 神呼喚那人,對他說:「你在那裡?」他說:「我在園中聽見你的聲音,我就害怕;因為我赤身露體,我便藏了。」

聖經這邊有個很有趣的地方,在於描述亞當和夏娃眼睛明亮了。一般來說眼睛明亮應該是好事,可是在這裡卻似乎不是這麼一回事。當亞當夏娃眼睛明亮後,他們開始用自己的眼光來看自己以及上帝。看自己,覺得赤身露體,非常羞恥;看上帝,從一開始的親密,變成害怕、恐懼。從那時候開始,人對於看見神這件事情就喪失了恩典,當人看見上帝,感到的不再是安心,而是充滿著罪惡感,寧可逃離創造天地的主。之後還有誰看見過神呢?或是提出想要看見神的要求呢?繼續一個一個往下數。

出33:18-23 摩西說:「求你顯出你的榮耀給我看。」耶和華說:「我要顯我一切的恩慈,在你面前經過,宣告我的名。我要恩待誰就恩待誰;要憐憫誰就憐憫誰」;又說:「你不能看見我的面,因為人見我的面不能存活。」耶和華說:「看哪,在…

當 send 被 Block 的時候

今天在工作上遇到一個問題。有兩個 process ( process A 和 process B ) 透過 unix domain socket 彼此在傳遞資料,結果發現 process A 在送資料到 process B  的時候,程式居然卡在 send 這支系統函式。send 是會卡住的函式嗎?

答案是:會!來看看「男人」怎麼說:

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

When the message does not fit into the send  buffer  of  the  socket,  send()  normally blocks, unless the socket has been placed in nonblocking I/O mode.  In nonblocking mode it would fail with the error EAGAIN or EWOULDBLOCK in this case.   The  select(2)  call may be used to determine when it is possible to send more data.

意思是當呼叫 send 的時候,send 會先將資料放到 kernel 的 buffer,如果 buffer 已經放不進去了,而且 send 又處於 BLOCK 的模式時,這時候 send 就會卡住。而為什麼 buffer 會滿呢?因為 process B 處理封包的時間過久,進而造成 kernel buffer 被 process A 源源不絕的封包給塞滿了,然後 process A 的 send 就被 block 了。解決這個問題的方法可以將 socket 設成 non-blocking mode,或是在傳送封包的時候把 flag 設成 MSG_DONTWAIT。而這也就是為什麼 epoll, select 這類的函式需要去偵測 fd 是否已經是可寫狀態的原因。不過更根本要處理的問題是,為什麼 process B 會處理一個封包處理這麼久啊 ...

放上測試用的小程式:

unix domain socket receiver:
sleep(10) 用來模擬處理…

年金改革

電影「投名狀」裏面有一段非常經典的台詞:

「兵不厭詐,這是戰爭」
「人無信就是畜生」

以我個人而言,從作戰的角度來看,謀略、算計都是必要的。但放到其他方面呢?例如像這邊的年金改革這樣的題目 ...

很多人會認為這些公教人員享有非常多的福利,像是寒暑假(話說老師如果有寒暑假的話,那些暑期輔導是怎麼回事)之類的,然後感覺又很輕鬆(恩,教過這些學生以後我真的覺得超累的),現在還享有非常優渥的年金方案實在是太不合理了,特別是在現在國家財政出問題的狀況下。而前陣子這群人走上了街頭抗議,更被有些人定位為剝削階級的人在捍衛尊嚴。說真的,我不贊成這種論點。

 我認為,當國家認用這群公務員、這些老師的時候,答應要給的福利就是要給,因為這是白紙黑字的契約,這是國家誠信的問題。的確,年金必須要改革,因為很多契約制定的時候都把經濟趨勢想像的太美好了,我剛工作的時候起碼聽到了5個保險業務推銷產品,每一個都是用年報酬率 8% 在算的,還告訴你這是低估,10 年以後的現在就知道當時到底有多樂觀了。但是改革不當溯及既往,因為那是契約,是這些人當初答應擔任這角色時所拿到的承諾。試想今天在職場上,老闆直接說營運不好,從現在起薪水砍半,這個老闆能被接受嗎?當然以台灣現在的環境,這種人愈來愈多,以壓榨他人為自己得利,我無法否認,這是人性,但我們現在談的是該不該做這種事情,是所謂倫理、道德的問題。

該想的是,為什麼早就該改革的東西會一直被放在那邊不動呢?不過這些不就是大家選擇出來的官員所做的決定嗎?錢付不出來怎麼辦,那就破產吧 ... 這是我的看法。沒有誠信的國家,又怎會期待國民會聽國家的話呢?

 民無信不立。

學術研究的一些想法

長官:「你的博士研究和公司的計劃有沒有關係?」
我:「沒有,我對博士班的研究有不一樣的期待 ...」
長官:「好好好,不要再囉唆了」

總算通過博士口試,某種程度上算是可以對的起自己的名字了:p,可是上面的那段對話一直在我的腦海中。我發現近些年來,每當社會在談到學術研究的時候,大家最常聯想到的一個詞是「象牙塔」,意思是這些是不食人間煙火、不知民間疾苦的傢伙,做的研究往往「沒有用」。什麼叫作「沒有用」?我認為用白話文來說就是「這能賺錢嗎?」以至於現在的老師要跟科技部申請計劃的時候一定都會有一個章節在談「效益」,而最好的寫法就是這個研究可以技轉給某家廠商,帶來多少的營收。寫的愈漂亮,計劃通過的機率就愈高,分的經費也會愈多。

這真的是研究嗎??

其實我很討厭這種氛圍。對我來說,象牙塔不見得是壞事,因為研究人員可以任自己的思想翱遊,不拘泥於大地,才有飛翔的可能。這才叫作創造力!當台灣自己把名為「務實」的限制加在研究人員身上的時候,又怎麼能期待能帶來創新的成果呢?舉例來說,Craig Gentry 在2009年提出了舉世聞名的 Fully Homomorphic Encryption。把這研究放在台灣,大家可以想想審查委員會怎麼問。

請問這研究有用嗎?
當然囉,它解決了密碼學界長久以來的一個 Open Problem,也就是 Homomorphic Encryption 有沒有可能同時滿足加法和乘法兩種運算 ...
我是問它可以用在哪裡?
喔,像是在加密過的資料庫做 SQL Query 啊還有 ...
有廠商技轉了嗎?
ㄜ,沒有ㄟ
有實作出來了嗎?
有,不過效能不怎麼好,而且還有 bootstrap 的問題,error rate 的問題 ...
就是不能用嘛,那我為什麼要支持你的研究?

同樣的題目還有量子電腦之類的。我們太習慣把經濟學的那一套拿來做評分了。當然,經濟學最根本的問題就是,「資源有限、慾望無窮」,所以總要做個評比來決定錢要給什麼樣的題目。這也是人文、哲學預算愈來愈少的原因。也因此,台灣的學生愈來愈缺少邏輯思考、發想創造的能力。

如果可以,我真希望起碼在這學術的象牙塔裏面,還能保有向天空飛翔的可能性。就算會如伊卡洛斯一般墜落,但起碼飛過。
















靈修分享:過去與未來的眼光

彼後 3:3-7
第一要緊的,該知道在末世必有好譏誚的人隨從自己的私慾出來譏誚說:主要降臨的應許在哪裡呢?因為從列祖睡了以來,萬物與起初創造的時候仍是一樣。他們故意忘記,從太古,憑神的命有了天,並從水而出、藉水而成的地。故此,當時的世界被水淹沒就消滅了。但現在的天地還是憑著那命存留,直留到不敬虔之人受審判遭沉淪的日子,用火焚燒。 

這是彼得寫給教會的第二封信,很有趣的地方在於拿到現在來居然異常的貼切。科學和信仰到底有沒有衝突?這是現在這個時代基督徒所面對最大的一個挑戰。有些基督徒認為:「信仰和真科學沒有衝突」,所以凡有衝突的都歸納為是人類理性還沒發展到這個地步,無法驗證。以我個人的立場來說,對上帝的認識不該被限制於人的理性之下,當我們要去認識、親近這位創造宇宙萬有的主宰時,又怎麼能將上帝置於人的理性、科學方法之下呢?所以從一開始這個問題就錯了。使徒行傳中保羅說:「創造宇宙和其中萬物的神,既是天地的主,就不住人手所造的殿,也不用人手服事,好像缺少什麼;自己倒將生命、氣息、萬物,賜給萬人。 」同樣的,「創造理性的上帝,既是智慧的主,就不受自然界的法則所拘束,也不需要人理性的推論、證明,不然就不存在一樣;自己倒將智慧、聰明、能力,賜給萬人」

可是對不信上帝的人來說呢?「萬物與起初創造的時候仍是一樣。」這就是人類推理的極限。 從歷史、過去的經驗來學習,但又有誰能看到起初上帝創造的作為,同樣地,又有誰能看到整個世界的結局。沒有!我們人所看到的範圍不過數十幾個寒暑,所以傳道書的作者才會在那邊說:「虛空的虛空,虛空的虛空,凡事都是虛空。人一切的勞碌,就是他在日光之下的勞碌,有什麼益處呢?一代過去,一代又來,地卻永遠長存。日頭出來,日頭落下,急歸所出之地。風往南颳,又向北轉,不住地旋轉,而且返回轉行原道。江河都往海裡流,海卻不滿;江河從何處流,仍歸還何處。萬事令人厭煩,人不能說盡。眼看,看不飽;耳聽,聽不足。已有的事後必再有;已行的事後必再行。日光之下並無新事。 」我們看不到起初、看不到末後,所以說「這一切都是捕風」「人在日光之下勞碌累心,在他一切的勞碌上得著什麼呢? 」。然而造我們的主卻是阿拉法和俄梅戛的上帝。

彼得在這裡提醒我們,要有過去未來的眼光。用過去的眼光來看,「起初,神創造天地」,萬物都上帝造的,既是上帝在掌管,我們就沒有什麼好害怕的。詩篇七十七篇的作者在經歷憂患後轉化了自…

為什麼 printf 印不出東西來?

一個簡簡單單的問題,隨手做個紀錄。下面這個小程式毫無意義可言,簡單來說就是印出 Hello World 以後進入無窮迴圈。
#include #include int main() { printf( "Hello World!!" ); while(1) { } return 0; }
問題來了,這個 printf 並沒有印出來 Hello World。可是把程式改成下面這個樣子就沒問題了。

#include #include int main() { printf( "Hello World!!\n" ); while(1) { } return 0; }
這是什麼原因呢?因為 printf 其實只是把東西放到 buffer 當中而不會立刻顯示。buffer 有三種模式,分別是 unbuffered, block buffered, line buffered。而預設的 stdout 是 line buffered,所以只有當遇到 '\n' 才會清空 buffer 把內容印出來,而 stderr 預設就是 unbuffered。要確保內容一定印的出來的方法,可以使用 fflush( stdout ),或是乾脆直接輸入下面的函式:

setbuf( stdout, NULL );

當 console 壞掉的時候 ...

這是今天在工作上看到的一個小技巧,所以把它記錄下來。在程式開發的過程中很容易會使用 print 的方式來追蹤並解決問題,以 C 來說最常見的就是 printf,如果要吐到 console 上的話就開啟 /dev/console 並使用 fprintf。 今天聽到的問題是:「版子的 console 壞掉了怎麼辦?」

最不花腦筋的答案:「換張版子吧~」

廢話,如果是這樣也不用紀錄了。我今天看到的作法紀錄在下面:

$ killall klogd
$ mv /dev/console /dev/console_bak
$ ln -sf /dev/pts/0 /dev/console

這作法真是太 cool 了,連程式都不用改唷,當然前題是你可以透過 terminal 連進去就是了。第1行的目的是少印一些資訊。

那 /dev/pts/0 是什麼東西呢?pts 是 pseudo terminal slave 的縮寫。細節可以 google 得到,這邊只講最簡單的,當有 terminal 連到 linux 主機時,主機會分派一個 pts 給他。舉例來說,我在 linux 啟動兩個 gnome-terminal,再透過 who 這個指令,可以看到下面的訊息:

$ who
neokent  tty7         2016-03-03 15:05 (:0)
neokent  pts/2        2016-03-03 15:06 (:0)
neokent  pts/5        2016-03-03 17:08 (:0)

其中 tty7 是我的桌面,pts/2 和 pts/5 是我的兩個 terminal。這時候如果在 pts/2 的 terminal 上執行 echo Hello > /dev/pts/5 可以在 pts/5 上看到 Hello 唷。