1. 程式人生 > >在Ubuntu 14.04 64bit上編譯並研究State Threads網路執行緒

在Ubuntu 14.04 64bit上編譯並研究State Threads網路執行緒

二、doc目錄研究 在st-1.9原始碼中doc目錄有幾個文件,可以參考 st.html  ST庫概論,winlin翻譯的那篇文章 timeout_heap.txt  超時heap實現 notes.html  給出了程式設計注意點,包括移植,訊號,程序內同步,程序間同步,非網路IO,超時處理,特別談到程序內同步非常簡單,不需要同步資源;非網路IO中談到drawback和設計時需要避免的方法 reference.html  一個API介面文件介紹,需要認真閱讀和熟悉,但是需要編碼實戰來加深理解 st_set_eventsys() 設定事件通知機制event notification mechanism,在st_init()之前呼叫, 建議優先選用ST_EVENTSYS_ALT,它會使用epoll,然後才是ST_EVENT_DEFAULT st_get_eventsys_name() 得到State thread庫當前使用的時間通知機制名稱,可能返回值是select,poll,kequeue,或epoll st _set_switch_in_cb(st_switch_cb_t cb) 設定thread被resume時的回撥函式,預設NULL
st_set_switch_out_cb(st_switch_cb_t cb) 設定thread被stop時的回撥函式,預設NULL st_randomize_stacks() 開啟或關閉stack base address randomization,開啟會提高效能,避免所有執行緒的stack是page aligned,而是隨機生成的 st_key_create() 為程序內的所有執行緒建立一個非負整數的key,以便去set和get thread-specific data,所有執行緒的key是一樣的但是存放的私有資料不同 st_thread_setspecific() 設定每個執行緒自己的私有資料,不同的執行緒可以對這個相同的key bindig不同的值 set_timecache_set() 將time caching開啟或是關閉, ST庫能夠快取time()庫函式報告的值,如果是realtime time應用,建議不要開啟該功能 set_time() 返回1970**以來的秒數 set_netfd_free() free file descriiptor但是不closing所在的os file descriptor st_readv() 從指定檔案描述符讀資料到multiple buffers中 最重要的是末尾的Program Structure,給出了在 一個網路應用程式中使用ST庫的基本步驟
: 1.假如願意,使用下面的pre-init函式配置ST庫,設定時間,事件通知機制 2.呼叫st_init()來初始化ST庫 3.假如願意,呼叫post-init函式來配置ST庫,設定timecache,隨機化執行緒棧,程序resume和stop的回撥函式 4.生成不同process之間共享的資源,建立並繫結socket,開啟socket,生成共享記憶體段,IPC channel和同步原語primitives 5.建立多程序,fork(), 父程序退出或是watchdog 6.在子程序中建立thread pool來處理user connection,執行緒池中的每個執行緒可以accept client connection,connect到其他伺服器,執行各種network I/O等等 每個process的每個socket的空閒執行緒spare thread的最大個數預設為8, server一啟動就建立執行緒池,它是最大空閒執行緒個數,執行緒池可以增長到最大執行緒個數,也可以限制匯流排程個數,而非針對每個listening socket 注意:只有ST庫的I/O函式可以用於 network I/O,其他的I/O calls都可能阻塞呼叫程序 三、example目錄 下面研究example目錄下面的3個例子 首先閱讀裡面的README,它簡單介紹了這三個例子的基本情況和用法 server 包含server.c和error.c lookupdns 包含lookupdns.c和res.c proxy 包含proxy.c 1.server.c程式分析: General server example, accept a client connection and just outputs a short html page 先定義程序陣列,個數是 vp_count
,是當前CPU的core數,這樣能充分利用CPU多核能力,再定義listening socket陣列 srv_socket[],個數是 sk_count,再定義其上每個srv_socket的wait for thread和busing thread個數。每個程序一個執行緒池在運轉,都在獨立地執行 在每個process中啟動執行緒數時,先建立access log flushing thread,它的職責是定期(配置為30s)寫日誌,然後是建立connection handling threads,它的職責是首先儲存連線雙方的ip和port,不管對方發的啥,悶頭就向對方傳送一個"It worked!"的html頁面, 然後關閉該tcp連線,參見執行緒函式handle_connections,它呼叫handle_session() 在建立socket並繫結偵聽時,ST的socket fd是使用st_netfd_open_socket(sock)得到的,就是在該sock上面得到的。 在C/S互動過程中,使用到執行緒私有資料方法來儲存listening socket index和client的sockaddr 整個程式的架構值得我們借鑑。 程式使用方法 ./server  -l ./          指定訪問日誌目錄,必須指定,下面都是可選引數              -b 127.0.0.1:8000 binding and listening sockets對數,否則使用0.0.0.0:8000代替              -p  8         生成程序個數,預設按照CPU核心個數定              -t   2:10    每個listening socket上的thread limits              -u  taoyx   指定執行該程式的user名,據此找出其group名和user名             -q   1000   待處理連線佇列的長度             -a              啟用訪問日誌記錄             -i               以互動模式執行嗎?否則以daemon守護程序執行。互動模式不記錄日誌資訊,建議命令列除錯時使用             -S              Serialize all accept() calls,依據平臺來確定             -h              print usage info 為了簡單,我直接使用預設命令開啟 ./server -l ./ 下面使用curl作為客戶端來測試 curl -vx 127.0.0.1:8000 -o a.html "http://news.sohu.com" 伺服器返回的固定page內容如下 通過傳送訊號來研究程序的行為 使用kill -l來列出所有的訊號編碼表,我們這裡只需要使用到SIGHUP(1), SIGUSR1(10), SIGTERM(15) kill  -10   4044   dump info列印當前各程序的偵聽埠,執行緒池執行緒情況,請求資訊
kill -1 4044  重啟程序,重讀配置檔案 kill -15 4044 終止程序,讓程式退出 這兩種方式在命令列沒有結果顯示,只能從日誌檔案error中看出響應細節
2.res.c分析 _res從哪兒來的? dns_getaddr() ==>query_domain()==> res_mkquery() ==> dn_skipname(), dn_expand(),                                                            ||==>parse_answer() lookupdns.c分析 非同步host name解析,一個host name對應一個ST執行緒,所有的執行緒都是併發的,查詢成功後打印出host name和對應的ip地址 使用方法 ./lookupdns www.baidu.com news.sohu.com new.sina.com.cn  www.ifeng.com v.youku.com
原始碼分析 main() ==> do_resolve() ==>dns_getaddr() ==> 引用res.c中的函式 3.proxy.c分析 該程式充當一個普通的gateway,它在本地地址監聽, 一接收到client connection,就連線到指定的遠端地址,獲取響應,不加修改地轉發給client 使用方法 -l  127.0.0.1:8086    本地偵聽的ip和port -r  1.2.3.4: 80              遠端連線的ip和port, 如果不是點分十進位制 -p  8                           並行程序個數,如果不指定,預設使用CPU的核心數 -S                               serialize accept -a                               使用alternate備用的事件通知機制,比如 epoll,它會呼叫ST_EVENTSYS_ALT設定st_set_eventsys(ST_EVENTSYS_ALT) -t  mask                     測試或除錯模式,掩碼為1,4,8,16,這裡選擇1,列印所有資訊 -X                               只用一個程序,不使用守護程序方式 使用下面的命令啟動 ./proxy -l 127.0.0.1:8086 -r news.sohu.com:80 -t 1 我們看到會分別起4個程序獨立工作,這樣停止這些執行緒比較麻煩,只能手動kill掉各個程序 kil -9 13458 kil -9 13459 kil -9 13460 kil -9 13461 現在使用curl做客戶端測試 curl -vx 127.0.0.1:8086 -o sohu.html "http://news.sohu.com"  得到的網頁可以在chrome中正常開啟 可見代理功能是完備的。另外我們可以設定mask的不同值來研究st_write_resid等介面函式的用法。 深入調研工作 1.dns查詢是如何實現的?