• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Just enjoy programming

            #

            linux RPC 測試(轉(zhuǎn)載)

            轉(zhuǎn)自:
            http://www.justwinit.cn/post/3960/


            RPC是glibc提供的函數(shù)參數(shù)/返回值封裝服務(wù), 并將封裝結(jié)果通過網(wǎng)絡(luò)傳到服務(wù)器.
            RPC服務(wù)端首先要啟動portmapper服務(wù).
            測試一個簡單的RPC傳輸示例, 先定義一個模板文件test.x

            program TESTPROG{
                    version VERSION{
                            int int_echo(int)=1;
                            int get_str_len(string)=2;
                            int add ( int, int ) = 3;
                    }=1;
            }=30000;
            內(nèi)含3個函數(shù), 注意其中一個有2個參數(shù).
            然后可以用rpcgen生成一個Makefile:

            rpcgen -a -N test.x

            這會生成Makefile, 客戶端和服務(wù)端的程序, 和函數(shù)示例.
            我們手工修改一下Makefile

            # This is a template Makefile generated by rpcgen
            # Parameters
            CLIENT = test_client
            SERVER = test_server
            SOURCES_CLNT.c =
            SOURCES_CLNT.h =
            SOURCES_SVC.c =
            SOURCES_SVC.h =
            SOURCES.x = test.x
            TARGETS_SVC.c = test_svc.c test_server.c test_xdr.c
            TARGETS_CLNT.c = test_clnt.c test_client.c test_xdr.c
            TARGETS = test.h test_xdr.c test_clnt.c test_svc.c
            OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
            OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
            # Compiler flags
            CFLAGS += -g -pipe
            LDLIBS += -lnsl
            RPCGENFLAGS = -N
            # Targets
            all : $(CLIENT) $(SERVER)
            $(TARGETS) : $(SOURCES.x)
                    rpcgen $(RPCGENFLAGS) $(SOURCES.x)
            $(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c)
            $(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c)
            $(CLIENT) : $(OBJECTS_CLNT)
                    $(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS)
            $(SERVER) : $(OBJECTS_SVC)
                    $(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)
            clean:
                     $(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)

            修改test_server.c服務(wù)端的處理函數(shù), 提供3種服務(wù):

            /*
            * This is sample code generated by rpcgen.
            * These are only templates and you can use them
            * as a guideline for developing your own functions.
            */
            #include "test.h"
            int *
            int_echo_1_svc(int arg1,  struct svc_req *rqstp)
            {
                    static int  result;
                    //echo.
                    result=arg1;
                    printf("[RPC1] source=%d, echo=%d\n", arg1, result);
                    return &result;
            }
            int *
            get_str_len_1_svc(char *arg1,  struct svc_req *rqstp)
            {
                    static int  result;
                    //get strlen.
                    result=strlen(arg1);
                    printf("[PRC2] str=%s, len=%d\n", arg1, result);
                    return &result;
            }
            int *
            add_1_svc(int arg1, int arg2,  struct svc_req *rqstp)
            {
                    static int  result;
                    result=arg1+arg2;
                    printf("[RPC3] %d+%d=%d\n", arg1, arg2, result);
                    return &result;
            }

            客戶端test_client.c, 調(diào)用這三種服務(wù):

            /*
            * This is sample code generated by rpcgen.
            * These are only templates and you can use them
            * as a guideline for developing your own functions.
            */
            #include "test.h"
            void
            testprog_1(char *host)
            {
                    CLIENT *clnt;
                    int  *result_1;
                    int int_echo_1_arg1=55;
                    int  *result_2;
                    char *get_str_len_1_arg1="Hello, world";
                    int  *result_3;
                    int add_1_arg1=10;
                    int add_1_arg2=20;
                    clnt = clnt_create (host, TESTPROG, VERSION, "udp");
                    if (clnt == NULL) {
                            clnt_pcreateerror (host);
                            exit (1);
                    }
                    result_1 = int_echo_1(int_echo_1_arg1, clnt);
                    if (result_1 == (int *) NULL) {
                            clnt_perror (clnt, "call failed");
                    }
                    else
                            printf("[PRC1] echo %d, source %d\n", *result_1,
                                    int_echo_1_arg1);
                    result_2 = get_str_len_1(get_str_len_1_arg1, clnt);
                    if (result_2 == (int *) NULL) {
                            clnt_perror (clnt, "call failed");
                    }
                    else
                            printf("[RPC2] return %d, should %d\n", *result_2,
                                    strlen(get_str_len_1_arg1));
                    result_3 = add_1(add_1_arg1, add_1_arg2, clnt);
                    if (result_3 == (int *) NULL) {
                            clnt_perror (clnt, "call failed");
                    }
                    else
                            printf("[PRC3] %d+%d=%d\n", add_1_arg1, add_1_arg2,
                                    *result_3);
                    clnt_destroy (clnt);
            }
            OK, 可以調(diào)用make了.
            生成可執(zhí)行程序test_server和test_client.
            我們啟動./test_server, 用rpcinfo看看:

            $rpcinfo -p 127.0.0.1
            program vers proto port
            100000 2 tcp 111 portmapper
            30000 1 udp 36307
            30000 1 tcp 34883
            Bingo! 啟動成功.

            再開個終端, 嘗試一下調(diào)用.

            ./test_client 127.0.0.1
            [PRC1] echo 55, source 55
            [RPC2] return 12, should 12
            [PRC3] 10+20=30

            正是我們期望的.

            Add By:Jackxiang
            make -f Makefile.test

            posted @ 2011-08-07 16:44 周強 閱讀(1173) | 評論 (0)編輯 收藏

            最近的我

               最近的我狀態(tài)不錯,睡眠也好了很多,每天7點半左右起床,每天看看資料,看看論文,編編程序,晚上10點半左右回到宿舍,洗個澡上上網(wǎng)就睡覺了,周末去圖書館看看書或者實驗室待著。這樣的生活挺好的,就是現(xiàn)在每天坐車有點累。現(xiàn)在的心態(tài)確實不錯,不再多想了,不再去想以后會去哪,以后該做什么,一切都隨緣吧,每天都盡量努力點,把能做的事給做好。
               最近的動車相撞確實挺讓人糾心的。單就技術(shù)方面我感覺我們的高鐵和動車還是有很大問題的,有點大躍進,買國外的技術(shù)然后自己改裝下,就說是處于世界領(lǐng)先水平了。技術(shù)的創(chuàng)新是需要長時間的積累的,我感覺我們目前最多只是個模仿者,更別談創(chuàng)新了。我感覺很多方面我們是缺少創(chuàng)新的,單就計算機方面,國內(nèi)最近炒得很熱的云計算,好像很多公司都在搞,看上去很創(chuàng)新,但我感覺是缺乏技術(shù)積累的,很多公司目前只是在用國外的開源軟件做做研究,到目前為止都沒有一個像亞馬遜,谷歌一樣的數(shù)據(jù)中心。

            posted @ 2011-07-31 20:18 周強 閱讀(270) | 評論 (3)編輯 收藏

            Nginx源碼分析-Epoll模塊(轉(zhuǎn)載)

            轉(zhuǎn)載自:http://www.tbdata.org/archives/1296


            Nginx源碼分析-Epoll模塊

            3 comments 十二月 26th, 2010 | by yixiao in 高性能服務(wù)器

            Linux平臺上,Nginx使用epoll完成事件驅(qū)動,實現(xiàn)高并發(fā);本文將不對epoll本身進行介紹(網(wǎng)上一堆一堆的文章介紹epoll的原理及使用方法,甚至源碼分析等),僅看一下Nginx是如何使用epoll的。

            Nginx在epoll模塊中定義了好幾個函數(shù),這些函數(shù)基本都是作為回調(diào)注冊到事件抽象層的對應(yīng)接口上,從而實現(xiàn)了事件驅(qū)動的具體化,我們看如下的一段代碼:

            ngx_event_module_t  ngx_epoll_module_ctx = {
                &epoll_name,
                ngx_epoll_create_conf,               /* create configuration */
                ngx_epoll_init_conf,                 /* init configuration */
                {
                    ngx_epoll_add_event,             /* add an event */
                    ngx_epoll_del_event,             /* delete an event */
                    ngx_epoll_add_event,             /* enable an event */
                    ngx_epoll_del_event,             /* disable an event */
                    ngx_epoll_add_connection,        /* add an connection */
                    ngx_epoll_del_connection,        /* delete an connection */
                    NULL,                            /* process the changes */
                    ngx_epoll_process_events,        /* process the events */
                    ngx_epoll_init,                  /* init the events */
                    ngx_epoll_done,                  /* done the events */
                }
            };
            


            這段代碼就是epoll的相關(guān)函數(shù)注冊到事件抽象層,這里所謂的事件抽象層在前面的博文中有提過,就是Nginx為了方便支持和開發(fā)具體的I/O模型,從而實現(xiàn)的一層抽象。代碼后面的注釋將功能說明得很詳細(xì)了,本文就只重點關(guān)注ngx_epoll_init和ngx_epoll_process_events兩個函數(shù),其他幾個函數(shù)就暫且忽略了。

            ngx_epoll_init主要是完成epoll的相關(guān)初始化工作,代碼分析如下:

            static ngx_int_t
            ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
            {
                ngx_epoll_conf_t  *epcf;
            	/*取得epoll模塊的配置結(jié)構(gòu)*/
                epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
            	/*ep是epoll模塊定義的一個全局變量,初始化為-1*/
                if (ep == -1) {
                	/*創(chuàng)一個epoll對象,容量為總連接數(shù)的一半*/
                    ep = epoll_create(cycle->connection_n / 2);
                    if (ep == -1) {
                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                                      "epoll_create() failed");
                        return NGX_ERROR;
                    }
                }
            	/*nevents也是epoll模塊定義的一個全局變量,初始化為0*/
                if (nevents events) {
                    if (event_list) {
                        ngx_free(event_list);
                    }
            
            		/*event_list存儲產(chǎn)生事件的數(shù)組*/
                    event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
                                           cycle->log);
                    if (event_list == NULL) {
                        return NGX_ERROR;
                    }
                }
                nevents = epcf->events;
            	/*初始化全局變量ngx_io, ngx_os_is定義為:
            		ngx_os_io_t ngx_os_io = {
                		ngx_unix_recv,
                		ngx_readv_chain,
                		ngx_udp_unix_recv,
                		ngx_unix_send,
                		ngx_writev_chain,
                		0
            		};(位于src/os/unix/ngx_posix_init.c)
            	*/
                ngx_io = ngx_os_io;
            	/*這里就是將epoll的具體接口函數(shù)注冊到事件抽象層接口ngx_event_actions上。
            	具體是上文提到的ngx_epoll_module_ctx中封裝的如下幾個函數(shù)
                    ngx_epoll_add_event,
                    ngx_epoll_del_event,
                    ngx_epoll_add_event,
                    ngx_epoll_del_event,
                    ngx_epoll_add_connection,
                    ngx_epoll_del_connection,
                    ngx_epoll_process_events,
                    ngx_epoll_init,
                    ngx_epoll_done,
            	*/
                ngx_event_actions = ngx_epoll_module_ctx.actions;
            #if (NGX_HAVE_CLEAR_EVENT)
            	/*epoll將添加這個標(biāo)志,主要為了實現(xiàn)邊緣觸發(fā)*/
                ngx_event_flags = NGX_USE_CLEAR_EVENT
            #else
            	/*水平觸發(fā)*/
                ngx_event_flags = NGX_USE_LEVEL_EVENT
            #endif
                                  |NGX_USE_GREEDY_EVENT /*io的時候,直到EAGAIN為止*/
                                  |NGX_USE_EPOLL_EVENT; /*epoll標(biāo)志*/
                return NGX_OK;
            }
            

            epoll初始化工作沒有想象中的復(fù)雜,和我們平時使用epoll都一樣,下面看ngx_epoll_process_events,這個函數(shù)主要用來完成事件的等待并處理。

            static ngx_int_t
            ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
            {
                int                events;
                uint32_t           revents;
                ngx_int_t          instance, i;
                ngx_uint_t         level;
                ngx_err_t          err;
                ngx_log_t         *log;
                ngx_event_t       *rev, *wev, **queue;
                ngx_connection_t  *c;
            	/*一開始就是等待事件,最長等待時間為timer;nginx為事件
            	專門用紅黑樹維護了一個計時器。后續(xù)對這個timer單獨分析。
            	*/
                events = epoll_wait(ep, event_list, (int) nevents, timer);
                if (events == -1) {
                    err = ngx_errno;
                } else {
                    err = 0;
                }
                if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
                    /*執(zhí)行一次時間更新, nginx將時間緩存到了一組全局變量中,方便程序高效的獲取事件。*/
                    ngx_time_update();
                }
            	/*處理wait錯誤*/
                if (err) {
                    if (err == NGX_EINTR) {
                        if (ngx_event_timer_alarm) {
                            ngx_event_timer_alarm = 0;
                            return NGX_OK;
                        }
                        level = NGX_LOG_INFO;
                    } else {
                        level = NGX_LOG_ALERT;
                    }
                    ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
                    return NGX_ERROR;
                }
            	/*wait返回事件數(shù)0,可能是timeout返回,也可能是非timeout返回;非timeout返回則是error*/
                if (events == 0) {
                    if (timer != NGX_TIMER_INFINITE) {
                        return NGX_OK;
                    }
                    ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                                  "epoll_wait() returned no events without timeout");
                    return NGX_ERROR;
                }
                log = cycle->log;
            	/*for循環(huán)開始處理收到的所有事件*/
                for (i = 0; i read;
            		。。。。。。。。。。。。。
            
            		/*取得發(fā)生一個事件*/
                    revents = event_list[i].events;
            
            		/*記錄wait的錯誤返回狀態(tài)*/
                    if (revents & (EPOLLERR|EPOLLHUP)) {
                        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
                                       "epoll_wait() error on fd:%d ev:%04XD",
                                       c->fd, revents);
                    }
                    if ((revents & (EPOLLERR|EPOLLHUP))
                         && (revents & (EPOLLIN|EPOLLOUT)) == 0)
                    {
                        /*
                         * if the error events were returned without EPOLLIN or EPOLLOUT,
                         * then add these flags to handle the events at least in one
                         * active handler
                         */
                        revents |= EPOLLIN|EPOLLOUT;
                    }
            		/*該事件是一個讀事件,并該連接上注冊的讀事件是active的*/
                    if ((revents & EPOLLIN) && rev->active) {
                        if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
                            rev->posted_ready = 1;
                        } else {
                            rev->ready = 1;
                        }
            
            			/*事件放入相應(yīng)的隊列中;關(guān)于此處的先入隊再處理,在前面的文章中已經(jīng)介紹過了。*/
                        if (flags & NGX_POST_EVENTS) {
                            queue = (ngx_event_t **) (rev->accept ?
                                           &ngx_posted_accept_events : &ngx_posted_events);
                            ngx_locked_post_event(rev, queue); /*入隊*/
                        } else {
                            rev->handler(rev);
                        }
                    }
                    wev = c->write;
            		/*發(fā)生的是一個寫事件,和讀事件完全一樣的邏輯過程*/
                    if ((revents & EPOLLOUT) && wev->active) {
                        if (flags & NGX_POST_THREAD_EVENTS) {
                            wev->posted_ready = 1;
                        } else {
                            wev->ready = 1;
                        }
            			/*先入隊再處理*/
                        if (flags & NGX_POST_EVENTS) {
                            ngx_locked_post_event(wev, &ngx_posted_events);
                        } else {
                            wev->handler(wev);
                        }
                    }
                }
                return NGX_OK;
            }
            

            本文將關(guān)注的兩個epoll函數(shù)也就這么一點代碼了,但整個epoll還有添加事件和刪除事件等的相關(guān)函數(shù),代碼都很簡單,本文就不做具體的分析了。

            posted @ 2011-07-10 00:54 周強 閱讀(935) | 評論 (0)編輯 收藏

            linux 進程間通信之消息傳遞

            linux 進程間通信中消息傳遞主要分為管道,F(xiàn)IFO,消息隊列
            (1)管道
            管道由pipe函數(shù)創(chuàng)建,提供一個單路(單向)數(shù)據(jù)流。pipe函數(shù)返回兩個文件描述符:fd[0]和fd[1]。前者打開來讀,后者打開來寫。管道沒有名字,所以只能由有親緣關(guān)系的進程使用。盡管管道是由單個進程創(chuàng)建的,它卻很少在單個進程內(nèi)使用。管道的典型用途為兩個不同進程(一個是父進程,一個是子進程)提供進程間的通信手段。首先,由一個進程(它將成為父進程)創(chuàng)建一個管道后調(diào)用fork派生一個自身的副本。接著,父進程關(guān)閉這個管道的讀出端,子進程關(guān)閉同一管道的寫入端。或者父進程關(guān)閉這個管道的寫入端,子進程關(guān)閉同一管道的讀出端。這就在父子進程間提供了一個單向數(shù)據(jù)流。

            (2)FIFO
            FIFO指代先進先出(First in,First out),linux中的FIFO類似管道。它是一個單向(半雙工)數(shù)據(jù)流。不同于管道的是,每個FIFO有一個路徑名與之關(guān)聯(lián),從而允許無親緣關(guān)系的進程訪問同一個FIFO。FIFO也稱為有名管道。FIFO由mkfifo函數(shù)創(chuàng)建。其中pathname是一個普通的Unix路徑名,它是該FIFO的名字。mkfifo 函數(shù)已隱含指定 O_CREAT|O_EXCL. 也就是說,它那么創(chuàng)建一個新的FIFO,要么返回一個EEXIST錯誤(如果所指定的名字的FIFO已經(jīng)存在)。如果不想希望創(chuàng)建一個新的FIFO,那就改為調(diào)用open而不是mkfifo.要打開一個已存在的FIFO或創(chuàng)建一個新的FIFO,應(yīng)先調(diào)用mkfifo,再檢查它是否返回EEXIST錯誤,若返回該錯誤則改為調(diào)用open.mkfifo 命令也能創(chuàng)建FIFO。可以從shell腳本或命令行中使用它。在創(chuàng)建出一個FIFO后,它必須或者打開來讀,或者打開來寫,所用的可以是open函數(shù),也可以是某個標(biāo)準(zhǔn)I/O打開函數(shù)。FIFO不能打開來既讀又寫,因為它是半雙工的。對管道或FIFO的write總是往末尾添加數(shù)據(jù),對它們的read則總是從開頭返回數(shù)據(jù)。如果對管道或FIFO調(diào)用lseek,那就返回ESPIPE錯誤。

            (3)Posix 消息隊列
            消息隊列可認(rèn)為是一個消息鏈表。有足夠?qū)憴?quán)限的線程可往隊列中放置消息,有足夠讀權(quán)限的線程可從隊列中取走消息。每個消息都是一個記錄,它由發(fā)送者賦予一個優(yōu)先級。在某個進程往一個隊列寫入消息之前,并不需要另外某個進程在該隊列上等待消息的到達。這跟管道和FIFO是相反的,對后者來說,除非讀出者已存在,否則先有寫入者是沒有意義的。一個進程可以往某個隊列寫入一些消息,然后終止,再讓另外一個進程在以后某個時刻讀出這些消息。消息隊列具有隨內(nèi)核的持續(xù)性,這跟管道和FIFO不一樣。Posix消息隊列和System V消息隊列。這兩組函數(shù)間存在許多相似性,但也有主要的區(qū)別
            1. 對Posix消息隊列的讀總是返回最高優(yōu)先級的最早消息,對System V消息隊列的讀則可以返回任意指定優(yōu)先級的消息。
            2.當(dāng)往一個空隊列放置一個消息時,Posix 消息隊列允許產(chǎn)生一個信號或啟動一個線程。System V消息隊列則不提供類似機制。

            隊列中的每個消息具有如下屬性:
            1.一個無符號整數(shù)優(yōu)先級(Posix)或一個長整數(shù)類型(System V).
            2.消息的數(shù)據(jù)部分長度(可以為0).
            3.數(shù)據(jù)本身(如果長度大于0)

            函數(shù)接口
            1. mqd_t mq_open(const char *name,int oflag,...)
            mq_open函數(shù)創(chuàng)建一個新的消息隊列或打開一個已存在的消息隊列
            2.int mq_close(mqd_t mqdes);
            mq_close函數(shù)關(guān)閉一個消息隊列。
            3.int mq_unlink(const char *name);
            從系統(tǒng)中刪除用作第一個參數(shù)的某個name.
            4. int mq_getattr(mqd_t mqdes,struct mq_attr *attr);
               int mq_setattr(mqd_t mqdes,const struct mq_attr *attr,struct mq_attr *oattr);
            每個消息隊列有四個屬性,mq_getattr返回所有這些屬性,mq_setattr則設(shè)置其中某個屬性。
            struct mq_attr{
               long mq_flags;
               long mq_maxmsg;
               long mq_msgsize;
               long mq_curmsgs;
            };
            5.int mq_send(mqd_t mqdes,const char *ptr,size_t len,unsigned int prio);
             int mq_receive(mqd_t mqdes,char *ptr,size_t len,unsigned int *priop);
            mq_send函數(shù)往消息隊列中寫入消息,mq_receive函數(shù)從消息隊列中讀出消息。

            6.int mq_notify(mqd_t mqdes,const struct sigevent *motification);
            結(jié)構(gòu)體:
            union sigval{
                int sival_int;
                void *sival_ptr;
            };

            struct sigevent
            {
                int sigev_notify;
                int sigev_signo;
                union sigval sigev_value;
                void  (*sigev_notify_function)(union sigval);
                pthread_attr_t *sigev_notify_attributes;
            };
            mq_notify函數(shù)為指定隊列建立或刪除異步事件通知。一些普遍適用于該函數(shù)的若干規(guī)則
            1).如果notification參數(shù)非空,那么當(dāng)前進程希望在一個消息達到所指定的先前為空的隊列時得到通知。我們說"該進程被注冊為接收該隊列的通知"。
            2).如果notification參數(shù)為空指針,而且當(dāng)前進程目前被注冊為接收所指定隊列的通知,那么已存在的注冊將被撤銷。
            3).任意時刻只有一個進程可以被注冊為接收某個給定隊列的通知。
            4).當(dāng)有一個消息達到某個先前為空的隊列,而且已有一個進程被注冊為接收該隊列的通知時,只有在沒有任何線程阻塞在該隊列的mq_receive調(diào)用中的前提下,通知才會發(fā)出。這就是說,在mq_receive調(diào)用中的阻塞比任何通知的注冊都優(yōu)先。
            5).當(dāng)該通知被發(fā)送給它的注冊進程時,其注冊即被撤銷。該進程必須再次調(diào)用mq_notify以重新注冊(想要的話)。

            參考:Unix進程間通信

            posted @ 2011-07-07 02:29 周強 閱讀(3031) | 評論 (3)編輯 收藏

            近期計劃

                 最近的思緒有點亂,離找工作只剩7,8,9三個月了,該是好好計劃下。
             (1)盡快把論文寫完
             (2)找工作前要要看完的書
            unix三卷書(就剩unix進程間通信),TCP/IP 詳解(卷一),c++編程思想2卷書,effective c++,STL源碼分析,設(shè)計模式,算法導(dǎo)論,編程之美,程序員面試寶典
            (3)源碼閱讀  nginx 閱讀

            posted @ 2011-07-06 12:37 周強 閱讀(328) | 評論 (4)編輯 收藏

                 晚上獨自一個人走在校園里,感覺特別的安靜,我喜歡這種平靜的生活,可能是因為這么多年一個人習(xí)慣了,有時候更喜歡一個人靜靜地待著,不用去理會其他人,可以獨自地思考。我感覺我以前缺少一個勇敢的心,不敢去追求一些美好的事物,錯過了很多東西。很多事是沒有對錯的,只在于自己的選擇。既然是自己做的選擇就不應(yīng)該去后悔什么,或許當(dāng)初不這樣選擇我會變得更好,但至少現(xiàn)在的我應(yīng)該感謝當(dāng)初的選擇,因為當(dāng)初的選擇才有現(xiàn)在的自己。突然想到了大姐說的一個詞“自律”,我感覺我有時真得太過自律了,有時候真想去放縱自己,羨慕那些把人生當(dāng)游戲的人,人生得意須盡歡,但我卻做不到,因為我知道我身上有很多責(zé)任,有很多事情需要去做。
                上周打家里電話,我爸問我是不是要放暑假了,我能聽出來他們想讓我回家看看了,我也很想回家看看,但最近我真得很忙,估計是沒時間回去了,只能等到過年的時候再回去了。
                上周末去醫(yī)院,發(fā)現(xiàn)有些數(shù)字確實有點高了,可能是因為長時間的壓力與睡眠不好造成的,是時候該為自己減減壓了,現(xiàn)在想想我真有點杞人憂天,很多事情我都可以不去想的。現(xiàn)在開始要堅持跑步鍛煉身體,好好改善睡眠了。要學(xué)會平靜地面對一切,簡單點,淡定點,不是非要做的事就不去想了,船到橋頭自然直。
               

            posted @ 2011-07-04 21:38 周強 閱讀(269) | 評論 (2)編輯 收藏

            linux 進程間通信綜述

            linux進程間通信主要分為以下4個領(lǐng)域
            (1)消息傳遞(管道,F(xiàn)IFO,消息隊列)
            (2)同步(互斥鎖,條件變量,讀寫鎖,信號量)
            (3)共享內(nèi)存區(qū)(匿名共享內(nèi)存區(qū),有名共享內(nèi)存區(qū))
            (4)過程調(diào)用(Solaris門,Sun RPC)


            linux進程間的信息共享可以分為
            (1) 基于文件系統(tǒng)的共享
            (2) 基于內(nèi)核的共享
            (3) 基于共享內(nèi)存區(qū)的共享


            IPC對象的持續(xù)性
            (1)隨進程間持續(xù)的IPC對象一直存在到打開著該對象的最后一個進程關(guān)閉該對象的最后一個進程關(guān)閉該對象為止。
            (2)隨內(nèi)核持續(xù)的IPC對象一直存在到內(nèi)核重新自舉或顯式刪除該對象為止。
            (3)隨文件系統(tǒng)持續(xù)的IPC對象一直存在到顯示刪除該對象為止。即使系統(tǒng)自舉了,該對象還是存在的。


            IPC類型                                       持續(xù)性
            管道                                           隨進程
            FIFO                                          隨進程

            Posix互斥鎖                                 隨進程
            Posix條件變量                              隨進程
            Posix讀寫鎖                                 隨進程
            fcntl記錄上鎖                                隨進程

            Posix消息隊列                              隨內(nèi)核
            Posix有名信號量                           隨內(nèi)核
            Posix基于內(nèi)存的信號量                   隨進程
            Posix共享內(nèi)存區(qū)                           隨內(nèi)核

            System V消息隊列                        隨內(nèi)核
            System V信號量                           隨內(nèi)核
            System V共享內(nèi)存區(qū)                     隨內(nèi)核

            TCP套接字                                  隨進程
            UDP套接字                                  隨進程
            Unix域套接字                               隨進程






            名字空間:
            當(dāng)兩個或多個無親緣關(guān)系的進程使用某種類型的IPC對象來彼此交換信息時,該IPC對象必須有一個某種形式的名字或者標(biāo)識符,這樣其中一個進程(往往是服務(wù)器)可以創(chuàng)建該IPC對象,其余進程則可以指定同一個IPC對象。

            IPC類型                        用于打開或創(chuàng)建IPC的名字空間                IPC打開后的標(biāo)識
            管道                                     沒有名字                                      描述符
            FIFO                                    路徑名                                         描述符

            Posix互斥鎖                          沒有名字                                      pthread_mutex_t指針
            Posix條件變量                       沒有名字                                      pthread_cond_t指針
            Posix讀寫鎖                          沒有名字                                      pthread_rwlock_t指針
            fcntl記錄上鎖                        路徑名                                         描述符

            Posix消息隊列                       Posix IPC名字                              mqd_t值
            Posix有名信號量                    Posix IPC名字                              sem_t指針
            Posix基于內(nèi)存的信號量            沒有名字                                     sem_t指針
            Posix共享內(nèi)存區(qū)                    Posix IPC名字                              描述符


            System V消息隊列                key_t鍵                                       System V IPC標(biāo)識符
            System V 信號量                  key_t鍵                                       System V IPC標(biāo)識符
            System V共享內(nèi)存區(qū)              key_t鍵                                      System V IPC 標(biāo)識符

            門                                      路徑名                                         描述符
            sun RPC                             程序/版本                                     RPC句柄

            TCP套接字                            IP地址與TCP 端口                         描述符
            UDP套接字                           IP地址與UDP端口                          描述符
            Unix域套接字                        路徑名                                        描述符  

            posted @ 2011-07-04 09:58 周強 閱讀(10874) | 評論 (3)編輯 收藏

               最近一直在下雨,有好幾次都被淋濕了,不過想想偶爾淋淋雨感覺也挺好的。我還是挺喜歡下雨的,可能跟我的性格有點關(guān)系,眼神中總有一絲的憂愁。記得小時候下雨的時候總喜歡坐在家門口的傻傻地看著雨。雨總能給我?guī)硪环N安靜的感覺,下雨天在實驗室看看書對于我來說可以算是一種享受,可以不去想一些煩心事,可以讓我浮躁的心靜下來。高中有空閑下來的時候喜歡讀會詩,雨巷是其中一首比較喜歡的詩。

            雨巷

            作者: 戴望舒

             
            撐著油紙傘,獨自
            彷徨在悠長、悠長
            又寂寥的雨巷
            我希望逢著
            一個丁香一樣地
            結(jié)著愁怨的姑娘
             
            她是有
            丁香一樣的顏色
            丁香一樣的芬芳
            丁香一樣的憂愁
            在雨中哀怨
            哀怨又彷徨
             
            她彷徨在這寂寥的雨巷
            撐著油紙傘
            像我一樣
            像我一樣地
            默默彳亍著
            寒漠、凄清,又惆悵
             
            她默默地走近
            走近,又投出
            太息一般的眼光
            她飄過
            像夢一般地
            像夢一般地凄婉迷茫
             
            像夢中飄過
            一枝丁香地
            我身旁飄過這女郎
            她靜默地遠(yuǎn)了、遠(yuǎn)了
            到了頹圮的籬墻
            走盡這雨巷
             
            在雨的哀曲里
            消了她的顏色
            散了她的芬芳
            消散了,甚至她的
            太息般的眼光
            丁香般的惆悵
             
            撐著油紙傘,獨自
            彷徨在悠長、悠長
            又寂寥的雨巷
            我希望飄過
            一個丁香一樣地
            結(jié)著愁怨的姑娘


            posted @ 2011-06-30 17:12 周強 閱讀(310) | 評論 (5)編輯 收藏

            linux 守護進程編寫規(guī)則

            linux 守護進程編寫規(guī)則

            (1)首先要做的是調(diào)用umask將文件模式創(chuàng)建屏蔽字設(shè)置為0.由繼承得來的文件模式創(chuàng)建屏蔽字可能會拒絕設(shè)置某些權(quán)限。
            (2)調(diào)用fork,然后使父進程退出(exit).這樣做實現(xiàn)了下面幾點:第一,如果該守護進程是作為一條簡單shell命令啟動的,那么父進程終止使得shell認(rèn)為這條命令已經(jīng)執(zhí)行完畢。第二,子進程繼承了父進程的進程組ID,但具有一個新的進程ID,這就保證了子進程不是一個進程組的組長進程。這對于下面就要做的setsid調(diào)用是必要的前提條件。
            (3)調(diào)用setsid以創(chuàng)建一個新會話,是調(diào)用進程:(a)成為新會話的首進程,(b)成為一個新進程組的組長進程,(c)沒有控制終端。在有些人建議在此時再次調(diào)用 fork,并是父進程終止。第二個子進程作為守護進程繼續(xù)運行。這樣就保證了該守護進程不是會話首進程。
            (4)將當(dāng)前工作目錄更改為根目錄。
            (5)關(guān)閉不再需要的文件描述符。這使守護進程不再持有從其父進程繼承來的某些文件描述符。
            (6)某些守護進程打開/dev/null使其具有文件描述符0,1,2.這樣,任何一個試圖讀標(biāo)準(zhǔn)輸入,寫標(biāo)準(zhǔn)輸出或標(biāo)準(zhǔn)出錯的庫例程都不會產(chǎn)生任何效果。

            參考:UNIX環(huán)境高級編程

            posted @ 2011-06-29 21:50 周強 閱讀(2167) | 評論 (1)編輯 收藏

            nginx源碼分析 ngx_palloc.h ngx_palloc.c

            ngx_palloc.h 和 ngx_palloc.c主要用于nginx管理內(nèi)存池

            #include <ngx_config.h>
            #include <ngx_core.h>


            /*
             * NGX_MAX_ALLOC_FROM_POOL should be (ngx_pagesize - 1), i.e. 4095 on x86.
             * On Windows NT it decreases a number of locked pages in a kernel.
             */
            #define NGX_MAX_ALLOC_FROM_POOL  (ngx_pagesize - 1)
            //內(nèi)存池默認(rèn)大小
            #define NGX_DEFAULT_POOL_SIZE    (16 * 1024)

            //#define ngx_align(d, a)     (((d) + (a - 1)) & ~(a - 1)) 將d向上取a的倍數(shù)。

            #define NGX_POOL_ALIGNMENT       16
            //內(nèi)存池的最小大小,為16的倍數(shù)
            #define NGX_MIN_POOL_SIZE                                                     \
                ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)),            \
                          NGX_POOL_ALIGNMENT)

            //ngx_pool_cleanup_pt 為函數(shù)指針
            typedef void (*ngx_pool_cleanup_pt)(void *data);

            typedef struct ngx_pool_cleanup_s  ngx_pool_cleanup_t;
            //這個結(jié)構(gòu)用來表示內(nèi)存池中的數(shù)據(jù)的清理handler
            //handler表示清理函數(shù),data表示傳遞給清理函數(shù)的數(shù)據(jù),next表示下一個清理handler,
            //也就是說當(dāng)destroy這個pool的時候會遍歷清理handler鏈表,然后調(diào)用handler.
            struct ngx_pool_cleanup_s {
                ngx_pool_cleanup_pt   handler;
                void                 *data;
                ngx_pool_cleanup_t   *next;
            };


            typedef struct ngx_pool_large_s  ngx_pool_large_t;
            //該結(jié)構(gòu)表示大塊內(nèi)存,這個結(jié)構(gòu)很簡單,就是一個指針指向下一塊large,一個alloc指向數(shù)據(jù)
            struct ngx_pool_large_s {
                ngx_pool_large_t     *next;
                void                 *alloc;
            };

            //數(shù)據(jù)區(qū)的指針ngx_pool_data_t。其中l(wèi)ast表示當(dāng)前的數(shù)據(jù)區(qū)的已經(jīng)使用的數(shù)據(jù)的結(jié)尾。
            //end表示當(dāng)前的內(nèi)存池的結(jié)尾。也就是說end-last就是內(nèi)存池未使用的大小。
            typedef struct {
                u_char               *last;
                u_char               *end;
            //指向下一塊內(nèi)存池
                ngx_pool_t           *next;
            //申請該內(nèi)存池失敗的標(biāo)記
                ngx_uint_t            failed;
            } ngx_pool_data_t;


            struct ngx_pool_s {
                ngx_pool_data_t       d;
                size_t                max;
                ngx_pool_t           *current;
                ngx_chain_t          *chain;
                ngx_pool_large_t     *large;
                ngx_pool_cleanup_t   *cleanup;
                ngx_log_t            *log;
            };


            typedef struct {
                ngx_fd_t              fd;
                u_char               *name;
                ngx_log_t            *log;
            } ngx_pool_cleanup_file_t;


            void *ngx_alloc(size_t size, ngx_log_t *log);
            void *ngx_calloc(size_t size, ngx_log_t *log);

            ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);
            void ngx_destroy_pool(ngx_pool_t *pool);
            void ngx_reset_pool(ngx_pool_t *pool);

            void *ngx_palloc(ngx_pool_t *pool, size_t size);
            void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
            void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
            void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);
            ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);


            ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);
            void ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd);
            void ngx_pool_cleanup_file(void *data);
            void ngx_pool_delete_file(void *data);


            #endif /* _NGX_PALLOC_H_INCLUDED_ */

            posted @ 2011-06-16 18:12 周強 閱讀(466) | 評論 (0)編輯 收藏

            僅列出標(biāo)題
            共6頁: 1 2 3 4 5 6 
            伊人久久五月天| 国产精品内射久久久久欢欢| 久久久久久国产精品无码下载| 久久国产亚洲精品无码| 久久婷婷五月综合国产尤物app| 一本色道久久综合狠狠躁篇| 人妻丰满?V无码久久不卡| 久久精品国产清自在天天线| 久久国产成人亚洲精品影院| 成人久久久观看免费毛片| 久久久久久精品免费看SSS| 青青草国产97免久久费观看| 欧美成a人片免费看久久| 精品伊人久久久| 久久夜色精品国产噜噜噜亚洲AV | 久久综合香蕉国产蜜臀AV| 18岁日韩内射颜射午夜久久成人 | 日日噜噜夜夜狠狠久久丁香五月| 综合久久国产九一剧情麻豆 | 久久国产乱子伦免费精品| 69国产成人综合久久精品| 精品999久久久久久中文字幕| 嫩草影院久久99| 久久综合九色欧美综合狠狠| 7777精品久久久大香线蕉| 久久亚洲国产午夜精品理论片| 久久久精品一区二区三区| 一本色道久久88综合日韩精品| 久久夜色精品国产噜噜噜亚洲AV| 国产99久久久久久免费看| 漂亮人妻被中出中文字幕久久 | 色欲久久久天天天综合网| 久久精品国产一区| 伊人久久大香线蕉综合Av| 亚洲国产精品婷婷久久| 久久综合久久综合亚洲| 国产精品久久亚洲不卡动漫| 中文字幕久久亚洲一区| 久久成人精品视频| 午夜精品久久久久久久久| 人妻中文久久久久|