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

            靜以修身,儉以養德,非澹薄無以明志,非寧靜無以致遠。
            隨筆 - 397, 文章 - 0, 評論 - 196, 引用 - 0
            數據加載中……

            bind源碼解析(一)

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

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

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

            main函數中,setup創建進程必要的服務,setup里比較重要的函數是create_managersns_server_createns_server_create主要是對一些結構體中的函數指針賦值還有用到的數據結構分配內存,create_managers啟動各種線程;

            isc_app_run則是見將on-run事件(通過管道)加入到任務隊列中,最終執行的是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)比較關鍵,將on-run事件到鏈表中,這個鏈表在isc_app_run里的for循環中被遍歷;

            Socket的初始化:

            setup(void)-> create_managers->isc__socketmgr_create2函數中:
            manager->common.methods = &socketmgrmethods;將函數指針賦值。ns_server_create(ns_g_mctx, &ns_g_server)
            CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),"isc_app_onrun");實際執行的是run_server函數
            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)這句代碼會調用上面賦給的函數地址(socketmgrmethods),將調用socketmgrmethodsisc__socket_create函數。前面闡述的是有關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函數指針賦值為client_request,即在這里給UDP的處理函數賦值(接收);發送同樣如此:這樣每進來一次udp就查詢一次,,會在task的run函數里執行active指針函數,進而調用這個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的關聯(和一些關鍵性代碼的說明):

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

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

            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++;
                          }
                   }

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

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

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

            }

            static void dispatch(isc__taskmgr_t *manager)里面有三個while循環
            //判斷(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);
            //實際執行的是isc_condition_wait((&manager->work_available), (&manager->lock)) == ISC_R_SUCCESS);-----------------> (pthread_cond_wait((&manager->work_available), &((&manager->lock)->mutex)) == 0,這里用來發信號,對互斥量加以保護,線程釋放互斥量,等待其他線程發給該條件變量的信號(喚醒一個等待者)或廣播該條件變量(喚醒所有等待者)。當等待條件變量時,互斥量必須始終為釋放的,這樣其他線程才有機會鎖住互斥量,修改條件變量。當線程從條件變量等待中醒來時,它重新繼續鎖住互斥量,對臨界資源進行處理。
            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);
             

                                             /**執行事件消息處理  */
            .........................................................

            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;

            /*在這個任務里沒有引用沒有待定的事件,這意味者不會有實際的事件(動作)發生,初始化關機以防止成為一個廢止(狀態)。替代"if EMPTY(task->events)"的原因:如果發送沒有關機事件,將派發一個結束任務;如果沒有派發關機事件,(總是)希望任務的總量是實際中(任務的總量)*/
             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) {

            /*(任務)總量用完,但是還有更多的work在做,將重新排列放到在準備隊列后。不必檢查總量直到至少派發一個事件,因此最小數是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

             

            2isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,unsigned int maxsocks)//創建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));//分配內存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;
                   }

            //創建管道-----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;
                   }

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

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

            評論

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

            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源碼解析(一)  回復  更多評論   

            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源碼解析(一)  回復  更多評論   

            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
            国内精品伊人久久久影院| 久久综合偷偷噜噜噜色| 精品久久久无码中文字幕天天| 久久无码一区二区三区少妇 | 久久久久无码专区亚洲av| 久久久久99精品成人片三人毛片| 日韩精品久久久久久久电影| 99久久777色| 亚洲第一永久AV网站久久精品男人的天堂AV | 国产精品美女久久久| 久久人人超碰精品CAOPOREN| 久久午夜无码鲁丝片| 久久久久亚洲AV无码专区网站 | 人妻中文久久久久| 国产精品99久久精品| 久久久久久精品久久久久| 久久精品国产精品亚洲下载| AAA级久久久精品无码片| 热久久最新网站获取| 国产成人久久777777| 777米奇久久最新地址| 18岁日韩内射颜射午夜久久成人| 久久青青草原精品国产软件| 中文字幕成人精品久久不卡| 麻豆一区二区99久久久久| 久久久久久极精品久久久 | 无码人妻久久一区二区三区蜜桃| 国产精品久久久亚洲| 久久一日本道色综合久久| 久久亚洲sm情趣捆绑调教| 精品一久久香蕉国产线看播放| 久久er热视频在这里精品| 久久久久国产精品熟女影院| 亚洲国产精品无码久久SM| 热久久视久久精品18| 少妇无套内谢久久久久| 2021国内久久精品| 中文精品久久久久人妻不卡| 天天躁日日躁狠狠久久| 亚洲色大成网站WWW久久九九| 亚洲av伊人久久综合密臀性色|