• <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>

            Benjamin

            靜以修身,儉以養(yǎng)德,非澹薄無以明志,非寧靜無以致遠(yuǎn)。
            隨筆 - 397, 文章 - 0, 評論 - 196, 引用 - 0
            數(shù)據(jù)加載中……

            bind源碼解析(一)

              Bind是一款開放源碼的DNS服務(wù)器軟件,Bind由美國加州大學(xué)Berkeley分校研發(fā)和維護的,全名為Berkeley Internet Name Domain他是目前世界上使用最為廣泛的DNS服務(wù)器軟件,支持各種unix平臺和windows平臺。官方網(wǎng)站:http://www.bind.com/

            下面介紹一下Bind軟件的主要的socket處理模塊:
            Bind
            業(yè)務(wù)處理主要要關(guān)注一個run函數(shù)和isc_app_run函數(shù),前者是線程函數(shù),相當(dāng)于一個消息泵,這個for循環(huán)作用通過管道發(fā)送事件,這個事件在到task里的run中被處理,如此反復(fù)和windows編程中的消息循環(huán)類似;

            Bind中的socket采用的是epoll模型,在main.c中的setup函數(shù)里的result = create_managers()->result = isc_socketmgr_create2(ns_g_mctx, &ns_g_socketmgr, maxsocks)-> setup_watcher;創(chuàng)建epool。if(isc_thread_create(watcher, manager, &manager->watcher) != ISC_R_SUCCESS) 啟動watcher這個線程函數(shù)process_fds來處理epoll,具體的處理函數(shù)是process_fd,根據(jù)不同的事件來執(zhí)行dispatch_accept(sock); dispatch_recv(sock); dispatch_connect(sock); dispatch_send(sock);這幾個函數(shù)最后執(zhí)行的都是isc_task_send(它的作用是將event加到task隊列中);

            main函數(shù)中,setup創(chuàng)建進程必要的服務(wù),setup里比較重要的函數(shù)是create_managersns_server_create;ns_server_create主要是對一些結(jié)構(gòu)體中的函數(shù)指針賦值還有用到的數(shù)據(jù)結(jié)構(gòu)分配內(nèi)存,create_managers啟動各種線程;

            isc_app_run則是見將on-run事件(通過管道)加入到任務(wù)隊列中,最終執(zhí)行的是isc__task_sendanddetach。在ns_server_create中的CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),"isc_app_onrun")里的ISC_LIST_APPEND(isc_g_appctx.on_run, event, ev_link)比較關(guān)鍵,將on-run事件到鏈表中,這個鏈表在isc_app_run里的for循環(huán)中被遍歷;

            Socket的初始化:

            setup(void)-> create_managers->isc__socketmgr_create2函數(shù)中:
            manager->common.methods = &socketmgrmethods;將函數(shù)指針賦值。ns_server_create(ns_g_mctx, &ns_g_server)
            CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),"isc_app_onrun");實際執(zhí)行的是run_server函數(shù)
            load_configuration->scan_interfaces(server, ISC_TRUE)->ns_interfacemgr_scan(server->interfacemgr, verbose)->ns_interfacemgr_scan0(mgr, NULL, verbose)-> do_scan->ns_interface_setup->if (accept_tcp == ISC_TRUE) {result = ns_interface_accepttcp(ifp);->isc_socket_create->manager->methods->socketcreate(manager, pf, type, socketp)這句代碼會調(diào)用上面賦給的函數(shù)地址(socketmgrmethods),將調(diào)用socketmgrmethodsisc__socket_create函數(shù)。前面闡述的是有關(guān)tcp的初始化,下面是udp的初始化:

            do_scan->ns_interface_setup->ns_interface_listenudp->ns_clientmgr_createclients->client_create->
            clclient->sendevent = (isc_socketevent_t *)
                   isc_event_allocate(client->mctx, client,
                        ISC_SOCKEVENT_SENDDONE,
                        client_senddone, client,
                        sizeof(isc_socketevent_t));
            client->recvevent = (isc_socketevent_t *)
                   isc_event_allocate(client->mctx, client,
                        ISC_SOCKEVENT_RECVDONE,
                        client_request, client,
                        sizeof(isc_socketevent_t));

            主要功能就是賦值ISC_EVENT_INIT(event, size, 0, NULL, type, action, deconst_arg,sender, destroy, mctx);active函數(shù)指針賦值為client_request,即在這里給UDP的處理函數(shù)賦值(接收);發(fā)送同樣如此:這樣每進來一次udp就查詢一次,,會在task的run函數(shù)里執(zhí)行active指針函數(shù),進而調(diào)用這個client_request

            switch (client->message->opcode) {
             case dns_opcode_query:
                          CTRACE("query");
                          ns_query_start(client);
                          break;
                   case dns_opcode_update:
                          CTRACE("update");
                          ns_client_settimeout(client, 60);
                          ns_update_start(client, sigresult);
                          break;
                   case dns_opcode_notify:
                          CTRACE("notify");
                          ns_client_settimeout(client, 60);
                          ns_notify_start(client);
                          break;

                   case dns_opcode_iquery:
                          CTRACE("iquery");
                          ns_client_error(client, DNS_R_NOTIMP);
                          break;
                   default:
             
                          CTRACE("unknown opcode");
                         ns_client_error(client, DNS_R_NOTIMP);
                   }

             

            Sockettask的關(guān)聯(lián)(和一些關(guān)鍵性代碼的說明):

            1、isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,isc_task_t **taskp)—創(chuàng)建ns_g_taskmgr,實參:ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr
             
            /*分配內(nèi)存*/manager = isc_mem_get(mctx, sizeof(*manager));返回的是ret = ctx->freelists[new_size];(ctx->memalloc)(ctx->arg, size);前者是鏈表的最后,后在則是分配的內(nèi)存的起始位置。
            manag的數(shù)據(jù)類型是isc__taskmgr_tctxisc__mem類型,ctx->freelistelement **           freelists,element則是typedef struct element element;
            struct element { 
                 
            element *            next;
            };

            //初始化條件變量(linux系統(tǒng)的函數(shù)) 一旦其它的某個線程改變了條件變量,它將通知相應(yīng)的條件變量喚醒一個或多個正被此條件變量阻塞的線程。這些線程將重新鎖定互斥鎖 并重新測試條件是否滿足。一般說來,條件變量被用來進行線程間的同步。

            if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) {
                          UNEXPECTED_ERROR(__FILE__, __LINE__,
                                         "isc_condition_init() %s",
                                         isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                                      ISC_MSG_FAILED, "failed"));
                          result = ISC_R_UNEXPECTED;
                          goto cleanup_threads;
                   }

                   /*初始化條件變量*/
                   if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) {
                          UNEXPECTED_ERROR(__FILE__, __LINE__,
                                         "isc_condition_init() %s",
                                         isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                                      ISC_MSG_FAILED, "failed"));
                          result = ISC_R_UNEXPECTED;
                          goto cleanup_workavailable;
                   }

             

            /*啟線程*/
                   for (i = 0; i < workers; i++) {
                          if (isc_thread_create(run, manager,
                                           &manager->threads[manager->workers]) ==
                              ISC_R_SUCCESS) {
                                 manager->workers++;
                                 started++;
                          }
                   }

            /*設(shè)置并發(fā)線程*/
            isc_thread_setconcurrency(workers);
            /*附加到特定的內(nèi)存塊上*/
            isc_mem_attach(mctx, &manager->mctx);muct的值賦給&manager->mctx。
            最后啟動線程。重點說明一下這個run線程函數(shù),這個線程函數(shù)使用來處理task的。run(void *uap) {

            …………………………………………………………………….
                   isc__taskmgr_t *manager = uap;
                   dispatch(manager);windowsDispatchMessage類似分發(fā)消息

            ……………………………………………………………………..
                   return ((isc_threadresult_t)0);

            }

            static void dispatch(isc__taskmgr_t *manager)里面有三個while循環(huán)
            //判斷(manager)->exiting && (manager)->tasks. .head == NULL
            while (!FINISHED(manager))
            while ((EMPTY(manager->ready_tasks) ||manager->exclusive_requested) &&!FINISHED(manager)) // 判斷(manager->ready_tasks).head ==NULL
            {、
            XTHREADTRACE(isc_msgcat_get(isc_msgcat,ISC_MSGSET_GENERAL,ISC_MSG_WAIT, "wait"));
            WAIT(&manager->work_available, &manager->lock);
            //實際執(zhí)行的是isc_condition_wait((&manager->work_available), (&manager->lock)) == ISC_R_SUCCESS);-----------------> (pthread_cond_wait((&manager->work_available), &((&manager->lock)->mutex)) == 0,這里用來發(fā)信號,對互斥量加以保護,線程釋放互斥量,等待其他線程發(fā)給該條件變量的信號(喚醒一個等待者)或廣播該條件變量(喚醒所有等待者)。當(dāng)?shù)却龡l件變量時,互斥量必須始終為釋放的,這樣其他線程才有機會鎖住互斥量,修改條件變量。當(dāng)線程從條件變量等待中醒來時,它重新繼續(xù)鎖住互斥量,對臨界資源進行處理。
            XTHREADTRACE(isc_msgcat_get(isc_msgcat,ISC_MSGSET_TASK,ISC_MSG_AWAKE, "awake"));
            }
            task = HEAD(manager->ready_tasks);
            if (task != NULL) {
            task->state = task_state_running;
                               XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                                   ISC_MSG_RUNNING, "running"));
                               isc_stdtime_get(&task->now);
            //遍歷鏈表
                               do {
                                      if (!EMPTY(task->events)) {
                                             event = HEAD(task->events);
                                             DEQUEUE(task->events, event, ev_link);
             

                                             /**執(zhí)行事件消息處理  */
            .........................................................

            if (event->ev_action != NULL) {
            UNLOCK(&task->lock);
             (event->ev_action)(   (isc_task_t *)task, event);
            LOCK(&task->lock);   
                                         
            }
                       
             
            dispatch_count++;
             } if (task->references == 0 && EMPTY(task->events) &&!TASK_SHUTTINGDOWN(task)) { isc_boolean_t was_idle;

            /*在這個任務(wù)里沒有引用沒有待定的事件,這意味者不會有實際的事件(動作)發(fā)生,初始化關(guān)機以防止成為一個廢止(狀態(tài))。替代"if EMPTY(task->events)"的原因:如果發(fā)送沒有關(guān)機事件,將派發(fā)一個結(jié)束任務(wù);如果沒有派發(fā)關(guān)機事件,(總是)希望任務(wù)的總量是實際中(任務(wù)的總量)*/
             was_idle = task_shutdown(task);                                
            INSIST(!was_idle);
             } 

                                      if (EMPTY(task->events)) {                       
                                         XTRACE(isc_msgcat_get(isc_msgcat,
                                                                 ISC_MSGSET_TASK,
                                                                 ISC_MSG_EMPTY,
                                                                 "empty"));
                                             if (task->references == 0 &&
                                                 TASK_SHUTTINGDOWN(task)) {
                                                   /*The task is done */
                                                   XTRACE(isc_msgcat_get(
                                                                  isc_msgcat,
                                                                  ISC_MSGSET_TASK,
                                                                  ISC_MSG_DONE,
                                                                 "done"));
                                                    finished = ISC_TRUE;
                                                    task->state = task_state_done;
                                             } else
                                                    task->state = task_state_idle;
                                             done = ISC_TRUE;
                                      } else if (dispatch_count >= task->quantum) {

            /*(任務(wù))總量用完,但是還有更多的work在做,將重新排列放到在準(zhǔn)備隊列后。不必檢查總量直到至少派發(fā)一個事件,因此最小數(shù)是1*/                                 XTRACE(isc_msgcat_get(isc_msgcat,
                                                                 ISC_MSGSET_TASK,
                                                                 ISC_MSG_QUANTUM,
                                                                 "quantum"));
                                             task->state = task_state_ready;
                                             requeue = ISC_TRUE;
                                             done = ISC_TRUE;
                                      }
                               } while (!done); 初始化是ISC_FALSE
                   ………

            } 

            注意:上面處理的是ns_g_taskmgr里的task。

             

            2、isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,unsigned int maxsocks)//創(chuàng)建ns_g_socketmgr
            實參:ns_g_mctx, &ns_g_socketmgr, maxsocks
            isc__socketmgr_t *manager;
            *managerp = (isc_socketmgr_t *)socketmgr;//初始化 

            manager = isc_mem_get(mctx, sizeof(*manager));//分配內(nèi)存manger的各個成員變量和方法賦值;

            ................................................
            //
            初始化manager->shutdown_ok—條件變量,和互斥對象配合使用在多線程編程中。
            if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
                          UNEXPECTED_ERROR(__FILE__, __LINE__,
                                         "isc_condition_init() %s",
                                         isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                                      ISC_MSG_FAILED, "failed"));
                          result = ISC_R_UNEXPECTED;
                          goto cleanup_lock;
                   }

            //創(chuàng)建管道-----epoll模型中使用
            if (pipe(manager->pipe_fds) != 0) {
                          isc__strerror(errno, strbuf, sizeof(strbuf));
                          UNEXPECTED_ERROR(__FILE__, __LINE__,
                                         "pipe() %s: %s",
                                         isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,\
                                                      ISC_MSG_FAILED, "failed"),
                                         strbuf);
                          result = ISC_R_UNEXPECTED;
                          goto cleanup_condition;
                   }

            //設(shè)置EPOLL中的事件和文件描述的關(guān)聯(lián)
            result = setup_watcher(mctx, manager);這個函數(shù)實際上執(zhí)行的是epoll_ctl(manager->epoll_fd, EPOLL_CTL_ADD, fd, &event);
            if (isc_thread_create(watcher, manager, &manager->watcher) !=ISC_R_SUCCESS)//啟動線程,實際執(zhí)行的是cc = epoll_wait(manager->epoll_fd, manager->events,
            manager->nevents, -1);開始監(jiān)聽管道里的事件,如果需要處理就處理。

            posted on 2010-12-20 21:44 Benjamin 閱讀(4012) 評論(3)  編輯 收藏 引用 所屬分類: linux

            評論

            # re: bind源碼解析(一)  回復(fù)  更多評論   

            When you are in a not good position and have no money to move out from that, you would require to take the <a href="http://bestfinance-blog.com/topics/home-loans">home loans</a>. Just because that will help you unquestionably. I get short term loan every time I need and feel good because of that.
            2011-09-08 14:39 | CAMERONMeredith19

            # re: bind源碼解析(一)  回復(fù)  更多評論   

            Do you see that you do great investigation just about this good post. Continue performing that! Students buy essay just about this opting for the term paper writing services.
            2011-10-07 06:25 | buy essays

            # re: bind源碼解析(一)  回復(fù)  更多評論   

            Tha’s really payless to receive hot enough fact referring to this good topic. But sometimes students switch on the personal computer and buy research paper and everybody could have the assistance of the high quality custom essays writing corporations to buy an essay fast.
            2011-10-09 02:18 | buy research papers
            日日狠狠久久偷偷色综合96蜜桃| 久久久久亚洲AV无码专区桃色| 国产高潮国产高潮久久久| 香蕉久久一区二区不卡无毒影院| 国产精品欧美亚洲韩国日本久久| 国产精品久久久久久久app| 国产精品久久午夜夜伦鲁鲁| 九九久久精品国产| 久久久久人妻精品一区| 欧美激情精品久久久久久| 97超级碰碰碰久久久久| 看全色黄大色大片免费久久久| 99久久精品国产麻豆| 久久久久久久波多野结衣高潮| 99久久精品免费观看国产| 无码人妻久久一区二区三区免费丨| 久久久WWW成人| 午夜不卡888久久| 久久99精品国产自在现线小黄鸭 | 久久精品国产亚洲AV忘忧草18| 91精品国产91久久| 精品综合久久久久久97超人 | 看久久久久久a级毛片| 日本三级久久网| 久久精品一区二区三区AV| 久久久精品波多野结衣| 久久精品国产亚洲一区二区| 五月丁香综合激情六月久久| 国产亚洲精品久久久久秋霞 | 国产精品久久久久9999高清| 精品久久久久久久国产潘金莲| 看全色黄大色大片免费久久久| 国产精品久久久久一区二区三区 | 久久精品国产亚洲AV无码偷窥| 老男人久久青草av高清| 亚洲欧美日韩精品久久亚洲区 | 色综合久久88色综合天天| 国产精品久久国产精麻豆99网站| 天天躁日日躁狠狠久久| 国产精品成人久久久久久久| 久久人人超碰精品CAOPOREN |