在Ubuntu 14.04 64bit上编译并研究State Threads网络线程库源码
生活随笔
收集整理的這篇文章主要介紹了
在Ubuntu 14.04 64bit上编译并研究State Threads网络线程库源码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
State Threads是一個廣受關注的高性能網絡線程庫,winlin在SRS中做了比較充分的應用,我很遺憾直到現在才精心研究它。下面是我的研究實錄,以作備忘。
一、源碼編譯
下面是在Ubuntu 14.04 64bit上面的實操記錄: 從官網http://sourceforge.net/projects/state-threads/下載源碼包,最新版是1.9,如果不能下載,就從github上下載fork版本 https://github.com/toffaletti/state-threads下載完st-1.9.tar.gz,然后解壓 tar zxvf st-1.9.tar.gz cd st-1.9 make linux-debug 然后會得到obj目錄。里面有生成的中間文件*.o, 頭文件st.h,libst.so,libst.a和example中的幾個例子:lookupdns,proxy,server等 下面我們在example中創建一個huge_threads.c并編譯。這個例子來自winlin文章中提供的.
//gcc -I../obj -g huge_threads.c ../obj/libst.a -o huge_threads
//./huge_threads 10000
//./huge_threads 30000
//#include <stdio.h>
#include "st.h"#define SLEEP_INTERVAL 30 //in msvoid* do_calc(void* arg){long pidx = *(long*)arg;for(;;){printf("sthread [#%ld] usleep\n", pidx);st_usleep(SLEEP_INTERVAL * 1000);}return NULL;
}int main(int argc, char** argv){if(argc <= 1){printf("Test the concurrence of state-threads!\n""Usage: %s <sthread_count>\n""eg. %s 10000\n", argv[0], argv[0]);return -1;}if(st_init() < 0){printf("state threads lib runtime init error!");return -1;}int i, count = atoi(argv[1]);for(i = 1; i <= count; i++){if(st_thread_create(do_calc, (void*)&i, 0, 0) == NULL){printf("create state thread %d failed\n", i);return -1;}}st_thread_exit(NULL);return 0;
}編譯gcc?-I../obj?-g?huge_threads.c?../obj/libst.a??-o?huge_threads
運行 ./huge_threads 10000 運行過程中,利用top查看程序性能,按ctrl+C中斷
注意st.h是動態生成的,這種方法值得學習
二、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守護進程運行?;幽J讲挥涗浫罩拘畔?#xff0c;建議命令行調試時使用 -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查找是如何實現的?
參考鏈接
[1].http://blog.csdn.net/win_lin/article/details/8242653? winlin的譯文,不錯,原文在源碼doc目錄中
[2].http://www.obroot.com/state-threads-for-internet-applications/?utm_source=tuicool? ?另一篇中文翻譯,不錯
[3].https://github.com/winlinvip/state-threads? ? ? ? ? ? ? ? winlin移植精簡版本
[4].http://sourceforge.net/projects/state-threads/? ?state-threads官網源碼
[5].http://coolshell.cn/articles/12012.html? ? ? ? ? ? ? 不可多得的心得薈萃
總結
以上是生活随笔為你收集整理的在Ubuntu 14.04 64bit上编译并研究State Threads网络线程库源码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在Ubuntu 14.04 64bit上
- 下一篇: 在Ubuntu 14.04 64bit上