標籤:style 使用 io 資料 ar 問題 cti 代碼
最近看了些libevent的源碼, 發現自己的技術還差的很遠。
之前寫程式總習慣自己實現。有的東西自己掌握不牢,或者沒有接觸到新的技術,總是用笨方法寫出不好看的代碼。之前對TCP/IP,網路編程不是很熟悉,實現的TCP用戶端斷線重連就很弱。 實現的伺服器端監聽連接埠,同時處理多個串連的程式,沒有理解清楚one connection one thread的思想,寫的代碼不夠簡潔高效。
還是在一次面試中遇到select/poll/epoll相關的問題,之後我才開始在網上以及書上注意到IO多工相關的東西。看了不少文檔,卻沒有實際使用過。心裡對epoll模型有點畏難的感覺。用過一點select。 最近有機會在網路通訊模組中使用epoll實現 事件驅動event loop模型。看了寫網上的範例代碼,發現使用起來很容易。linux系統庫帶的功能,介面也比較清晰。
epoll模型的epoll_data結構體的定義很巧妙,通過int和指標的聯合變數定義,讓使用時既可以直接使用socket fd,也可以自訂結構體。使ptr指向自訂結構體能夠提供很好的靈活性,有很多跟事件綁定的東西都可以組織起來,比如回呼函數,fd對應用戶端的狀態變遷等。這樣 事件處理的對象就不僅僅是一個IO fd了,可以是fd代表的其他東西。
The struct epoll_event is defined as :
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
最近也看到一個104規約解析的源碼mrts,它的資料結構定義的很巧妙,通過定義的struct,避免了頻繁的指標強制轉換。我之前自己實現的解析程式,主要就是將char類型的報文對應位置強制指標轉換來解析的,代碼複雜,可讀性太差。
/* CP56Time2a timestamp */
typedef struct cp56time2a {
u_shortmsec;
u_charmin:6;
u_charres1:1;
u_chariv:1;
u_charhour:5;
u_charres2:2;
u_charsu:1;
u_charmday:5;
u_charwday:3;
u_charmonth:4;
u_charres3:4;
u_charyear:7;
u_charres4:1;
} cp56time2a __attribute__((__packed__));
/* M_ME_NC_1 - short floating point measured value */
struct iec_type13 {
floatmv;
u_charov:1; /* overflow/no overflow */
u_charres:3;
u_charbl:1; /* blocked/not blocked */
u_charsb:1; /* substituted/not substituted */
u_charnt:1; /* not topical/topical */
u_chariv:1; /* valid/invalid */
}__attribute__((__packed__));
看了點git相關的東西。git和svn的文法還是比較像的,不同的主要是分布式和用戶端/伺服器模式的區別。另外git的分支branch看起來很有用,有機會一定要試試。
github上有很多不錯的源碼,配合git,以後閱讀源碼也方便了。
libevent庫中有時間事件的處理,裡面提到用小根堆來管理逾時時間,時間複雜度O(logn)。libevent用sockpair將 訊號的事件處理模型統一到event loop中,相當與將訊號處理轉化為IO模型。我也是只看了個大概。 之前一直以為 課程上學的堆,動態規劃等較複雜的資料結構和演算法工作中幾乎用不到,現在才知道不是用不到,是自己懶或者畏難。
最近改別人的代碼發現 變數命名,資料結構的定義,程式邏輯的設計,代碼注釋都是很重要的。代碼可讀性對維護,修改,升級的效率影響很大。同時,工作如果沒有責任心,對自己較高的要求,寫出的代碼往往漏洞百出,只能應付差事。這對於之後的維護是個災難。 整體的架構,邏輯設計,以及資料結構設計很重要。設計盡量簡單高效,層次過多會讓人難以理解,通常效率也不會好。
英語很重要。酷殼的陳皓都說英語是電腦工作人員很重要的一項技能。