2013年10月29日 星期二

multi thread in libev

Libev 是一個事件的library(event loop library)
透過loop與monitor的方式來做事件的處理
觸發不同的事件來執行不同的 callback
Libev 官方網站

這算是我工作上第一個遇到的新工具~
一開始看官方文件 還是霧煞煞~
不過 實際去RUN個幾次 你就會懂他的 邏輯與方式了~

這次要回頭處理 原本的ev 事件程式
想測試看看用 multi thread 來提升 處理效能

使用libev 如果希望工頭(主程序)隨時身邊都有工人(thread)待命,一有事情就派工人處理
但要讓工人處於待命狀態,而且又要聽命於工頭
其中 ev_async 是很重要的一個"秘書",可以幫忙與其他工人溝通


  ev_async async_watcher;
  ev_loop thread_loop;
  ev_io main_event;
  EV_P;

  int main()
  {
    loop = ev_default_loop(0);
    thread_loop= ev_loop_new(0);

    pthread_t thread;

    ev_async_init(async_watcher, async_cb);
    ev_async_start(thread_loop ,async_watcher);

    pthread_create(&thread, NULL, pthread_function, NULL);

    ev_io_init(&main_event, cb_main_callback, fd, EV_READ);
    ev_run(EV_A_ 0);
  }

  void *pthread_function(void *ptr)
  {
    ev_run(thread_loop, 0);
    pthread_exit(0);
    return NULL;
  }

  void cb_main_callback(EV_P_ ev_io *w, int revents)
  {
    if(ev_async_pending(&mthread[thread_count].async_watcher) == 0)
    {
      async_watcher.data = (void *)"Test Multi Thread";
      ev_async_send(thread_loop , &async_watcher);
    }
  }

  void async_cb(EV_P_ ev_async *w, int revents)
  {
    char * msg;
    msg = (char *)w->data
    printf("%s\n",msg);
  }

擷取程式中 部分程式碼說明一下 ev_async的 運作流程
首先主程序 在執行 ev_run(EV_A_ 0); 之前
註冊了一個 async_watcher 並指定 callback async_cb()
並啟 ev_async_start(thread_loop ,async_watcher);
在pthread_create() 的時候讓 thread_loop 運作 此時因為
有註冊async_watcher  所以不會 thread_loop  直接結束掉

再來重點在於 主程序 進到 cb_main_callback() 中
ev_async_pending() 這個動作 要跟 ev_async_send()
一起講會比較清楚
在ev_async_send()在 thread_loop 做個標記 此時會可以讓loop
去進到async_cb() 而此時會把 ev_async_send()所做的標記重置
而 ev_async_pending() 到底有啥作用呢
有人可能從字面上覺得 是在看是否呈現等待狀態
但實際的運作是
當已經被ev_async_send()標記 但loop並未觸發,則會回傳非0的值
所以我們必須判斷 ev_async_pending()等於0
才能再進行一次 ev_async_send()

通常在使用會遇到一個問題 就是 我需要帶資料或變數改怎麼處理
可能比較常看到 是使用 全域的變數 使用 lock 的方式
而其實 ev 事件 的monitor的struct 都會有一些變數可以使用
可以很方便在不同的callback傳遞

  struct ev_async {
    sig_atomic_t volatile sent;
    int active;
    int pending;
    int priority;
    void* data;
    void (*cb)(struct ev_loop *loop, struct ev_async *w, int revents);
  };

更多範例 可以在搜尋關鍵字 "libev thread" , "ev_async"
下面連結是 網路上的範例 自己有稍微修改測試了一下~
example ev_thread.c 

參考連結

http://www.codeday.net/?p=68 (libev 一些struct 結構)
http://stackoverflow.com/questions/14621261/using-libev-with-multiple-threads

2013年9月12日 星期四

Apache allow,deny rule

這幾天 有個新功能 用到了  apache 相關的設定
<Location /server-status>
    SetHandler server-status
    Order Allow,Deny
    Deny from  192.168.16.100
    Allow from 192.168.16.0/24
</Location>
設置網段後 又想獨立設定網段中某一個IP
也就是說 小範圍的設定 會優先於大範圍的
ex: 我想在 192.168.16.0/24 網段中 全部通過 但 只想其中某個 16.100 阻擋
此時該怎麼設定呢
上面這個設定 是可以達到這目的

一開始沒弄懂 他實際的條件與規則
想破頭都想不出該怎麼辦

後來才看到 上面這樣的寫法
但通常 我們會用 deny from all
他怎麼沒有擋 這樣好像怪怪的

後來又翻到下面這個表~~~
其中 Order Allow,Deny > 意指先比 允許的 在比 拒絕的
但他看的是最後比到的為主喔~
Match      | Allow,Deny result   | Deny,Allow result
-------------------------------------------------------
Allow only | Allowed             | Allowed
Deny only  | Denied              | Denied
No match   | Default: Denied     | Default: Allowed
Match both | Final match: Denied | Final match: Allowed
才恍然大悟阿~~~

預設是全部deny
狀況1 :   ip-deny,subnet-allow
>> 就等同第一個圖的方式

狀況2:  ip-allow,subnet-allow
<Location /server-status>
    SetHandler server-status
    Order Allow,Deny
    Allow from 192.168.16.100
</Location>
突然想到
其實 只要把加入的ip 去比對 目前允許的subnet 如果在其中才額外加deny就可以了

不過 沒有很詳細研究
因為不是我擅長的領域阿 ~ 只是碰到插個花
請多多指教囉~



2013年9月6日 星期五

認真比偷懶更糟糕

最近都沒寫程式的文章
因為......

  一堆客服問題 瘋狂地打斷寫程式的興致啊 ><!

慢慢的會有越來越多 程式之外的事情需要我去了解 處理
也沒有排斥 但會影響到寫程式的效率 也是真的~~

長越大 越來越發現 自己好像不太能一心二用
或許因為這樣 對單一事物的專注力十分的強
不是不能被打擾 而是你打擾不了我 ㄎㄎ

==== 跳一下  進入主題 ===

說道職場文化 我想就台灣目前的工作環境來說
似乎 都還是悲觀居多~

就像我今天也分享了一篇文章 (才不是夢幻工作!Facebook遭踢爆16件慘案)
自己覺得 不管你在多厲害多大間的甚至是 夢幻工作等等
多少 一定還是有 你看不慣的文化 或者 令人詬病的人事物

最近莫名的有點感觸
當上頭覺得 有人不夠認真 對公司貢獻的太少時
第一時間 我們總是會想說 有嗎?! 我很認真應該不是 說我吧...

但其實 最認真的你 對公司或對你自己來說 是更糟糕的情況

蛤 為啥?!!!

當一個公司大到一個規模 管理者可能已經沒有辦法 對屬下一個一個去監督
每天仔細地審視你做什麼
只能看成效 甚至可能用主觀的意識來評分你的表現

如果 我因為偷懶 被發現 表現不好
很簡單 就不要偷懶 認真一點 發揮100% 搞定!

對公司來說 要讓妳走也很好下決定 因為你偷懶麻!!!
再來就用一些獎逞制度 來強迫你認真點  搞定!

=*=

當你已經很認真 那真的糟糕了
也許 是你的能力 已經不符合 這間公司的要求 Over

對公司來說 不管你做什麼改變 這個人就只能這樣了
默默鼻子 想想 根本投資錯人了 Over

當然還有很多因素 不一定是能力的問題
但在職場上的一些經驗讓我感覺

反而最難處理的 卻是 大家都很好 很認真 很盡責
卻沒辦法 達到 要求時

到底是 哪個層級的問題?!
管理制度上 產生的問題嗎?
公司規模 跟要求程度的問題嗎?
真的用香蕉請到猴子了嗎?!

很複雜 ... 很難搞 = =|||

總結

盡我所能 多跟自己計較  而不是別人
重點~ 學習才是王道!!!





2013年8月29日 星期四

發呆型 程式設計

很久 沒在這寫心情了
颱風康芮 正在用颱風尾 騷擾台灣中
害得我 必須在風雨中上班 = =|||
雖說來上半 但心裡懸念著 電競的新歷史"小巨蛋的戰役" XD

最近對於寫程式 似乎沒有像以前那麼拼命了
有了幾次的經驗
慢慢的發現 有時候 停下來 多想一下
其實可以減少很多 不必要的問題與時間

有時候甚至 我花了 2.3個小時都在思考與查詢
在別人眼裡 可能跟發呆沒兩樣吧 XD
至於 真的寫程式碼的時間 可能不到一個小時吧~

此時 腦袋寫程式的功力 真的也很重要
現在我已經不隨便下手
以前都是 想到哪 就先動手 可能經過了好一段時間才發現
可能在前幾個步驟 就有問題
又得花時間去改 去修

但不少人 被時程追著跑
甚至寫程式也要有"業績"
每天都得擠出那幾行的程式碼來交差

環境麻!也不一定是自己能改變的~

不過
至少可以改變自己的心態吧
不奢求變成武林的高高手
但遇到問題 都還是願意抱著熱血往前衝
享受過五關斬六將的快感 -.-

開心地寫程式吧!! ^^!

2013年8月19日 星期一

openswan 問題 cc1: error: -Werror=cpp: No option -Wcpp

突然想來架設 一個  ipsec的 vpn server
找到文章
http://phorum.study-area.org/index.php?topic=58837.0
http://blog.xuite.net/misgarlic/weblogic/41607364-L2TP%2FIPSec
作參考
其中 需要安裝 opneswan

結果安裝時發現
出現以下訊息

make[3]: Entering directory `/PGRAM/openswan-2.6.39/OBJ.linux.i386/programs/pluto'

cc -g -O2 -fPIE -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security 

-Werror=format-security -D_FORTIFY_SOURCE=2 &nbsp;-DGCC_LINT &nbsp;
-I/PGRAM/openswan-2.6.39/ports/linux/include &nbsp;
-I/PGRAM/openswan-2.6.39/ports/linux/include &nbsp;
-I/PGRAM/openswan-2.6.39/ports/linux/include &nbsp;
-I/PGRAM/openswan-2.6.39/programs/pluto/linux26 
-I/PGRAM/openswan-2.6.39/include 
-I/PGRAM/openswan-2.6.39/lib/libcrypto 
-I/PGRAM/openswan-2.6.39/linux/include &nbsp; &
nbsp;-DPLUTO_SENDS_VENDORID -DUSE_KEYRR &nbsp;
-DDYNAMICDNS -DNETKEY_SUPPORT 
-DKERNEL26_HAS_KAME_DUPLICATES -DPFKEY -DX509_PLUTO &nbsp;
 -DPLUTO -DKLIPS -DHAVE_UDPFROMTO -DPFKEY &nbsp; 
-DKLIPS_MAST &nbsp; -DBUILDER=\"root@L7base\"
-DDEBUG -DUSE_AES -DUSE_3DES -DUSE_SHA2 -DIKE_ALG 
-DKERNEL_ALG -DAGGRESSIVE -DXAUTH -DMODECFG -DMODECFG_DNSWINS
&nbsp;-DNAT_TRAVERSAL 
-DI_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT &nbsp; 
&nbsp; &nbsp; &nbsp;
-DUSE_MODP_RFC5114 -DHAVE_NM -DSHARED_SECRETS_FILE=\"
/etc/ipsec.secrets\" -DPOLICYGROUPSDIR=\"
/etc/ipsec.d/policies\" -DPERPEERLOGDIR=\"
/var/log/pluto/peer\"
-g -Wall -W -Wmissing-prototypes -Wpointer-arith -Wbad-function-cast 
-Wcast-qual -Wmissing-declarations -Wwrite-strings -Wstrict-prototypes
&nbsp;-Wno-error=cast-qual -Wno-error=cpp -DALLOW_MICROSOFT_BAD_PROPOSAL &nbsp;
-c /PGRAM/openswan-2.6.39/programs/pluto/connections.c

cc1: error: -Werror=cpp: No option -Wcpp

make[3]: *** [connections.o] Error 1

make[3]: Leaving directory `/PGRAM/openswan-2.6.39/OBJ.linux.i386/programs/pluto'

make[2]: *** [programs] Error 1

make[2]: Leaving directory `/PGRAM/openswan-2.6.39/OBJ.linux.i386/programs'

make[1]: *** [programs] Error 1

make[1]: Leaving directory `/PGRAM/openswan-2.6.39/OBJ.linux.i386'

make: *** [programs] Error 2

=========================
關鍵問題在 cc1: error: -Werror=cpp: No option -Wcpp
疑似因為 使用的參數 我 gcc 版本似乎沒有支援

後續到網路上查看到相同的問題 
原因是 gcc的版本較舊 新版本的參數指令無法編譯

到下面這個連結  即可看到 修正的 Makefile 內容 (可自己動手改或直接覆蓋~)
[Only use -Wno-error=cpp when GCC's version is >= 4.6]
https://github.com/xelerance/Openswan/commit/31e261a07a1aa6b9de1491e8f6053189aff5554b

以下步驟即可搞定!
================


有兩個地方的  "Makefile" 使用到 造成問題的command

(1)lib/libopenswan/Makefile
(2)program/pluto/Makefile

在上面兩個檔案中找到這行 :
 "CFLAGS+= -Wno-error=cpp"

替換成 :
# Check if GCC's version is recent enough

GCC_VERSION_GE_46:=$(shell test `gcc -dumpversion | sed 's/^\([0-9]\)\.\([0-9]\).*/\1\2/'` -ge 46 && echo true || echo false)

ifeq ($(GCC_VERSION_GE_46),true)

 CFLAGS+= -Wno-error=cpp

endif
將會依照你的gcc版本 去判斷是否執行此段程式碼~