Bind-9.6.0-P1源代码分析之一:整体架构(初稿)


转载至:不知转载源

一、 说明

参考http://202.120.16.5/lxr/http/source/bin/named/main.c

这是bind解析程序的入口

事件bind程序也事件驱动型,以任务作为主要的执行。

当一个解析请求到来时,就会通过事件的产生来触发任务dispatch处理。这样的处理有相应

if (event->ev_action != NULL) {

861                                                 UNLOCK(&task->lock);

862                                                 (event->ev_action)(task,event);

863                                                 LOCK(&task->lock);

这里 action就是执行函数

本文主要关注整体的运行结构,主要参考文件是main.c

 

 

二、 启动入口

870 int

871 main(int argc, char *argv[]) { 命令行参数传入

以上为设置错误消息

895         isc_assertion_setcallback(assertion_failed);

896         isc_error_setfatal(library_fatal_error);

897         isc_error_setunexpected(library_unexpected_error);

898初始化系统日志,权限等

899         ns_os_init(program_name);

900初始化工作

901         dns_result_register();

902         dst_result_register();

903         isccc_result_register();

904 命令行参数分析,如-g将日志输出到front-end

905         parse_command_line(argc, argv);

 

{注意以下的内存机制,isc_mem可见http://202.120.16.5/lxr/http/source/lib/isc/mem.c#L113定义

注意以

http://202.120.16.5/lxr/http/source/lib/isc/mem.c#L725

用到了锁机制

830         LOCK(&lock);

831         ISC_LIST_INITANDAPPEND(contexts, ctx, link);

832         UNLOCK(&lock);

833 

内存生成采用标准的系统调用 malloc和free,但考虑到多线程下的竞争情况,对内存块访问需要锁机制。Ns_g_mctx是信号量,要求ns_g_mctx!=NULL&&*ns_g_mctx=NULL

}

919         result = isc_mem_create(0, 0, &ns_g_mctx);

 

 

920         if (result != ISC_R_SUCCESS)

921                 ns_main_earlyfatal("isc_mem_create() failed: %s",

922                                    isc_result_totext(result));

对设置

923         isc_mem_setname(ns_g_mctx, "main", NULL);

924 //setup是重要的一部分,见分析三

925         setup();

接下来就是解析主体程序了,是通过循环来做的,直到错误或者接收到退出信号。递

/*

928          * Start things running and then wait for a shutdown request

929          * or reload.

930          */

931         do {

932                 result = isc_app_run();是重要部分,见分析四

933 

934                 if (result == ISC_R_RELOAD) { //通过我们会做这种操作,当配置了一个新的zone文件时

935                         ns_server_reloadwanted(ns_g_server);

936                 } else if (result != ISC_R_SUCCESS) {

937                         UNEXPECTED_ERROR(__FILE__, __LINE__,

938                                          "isc_app_run(): %s",

939                                          isc_result_totext(result));

940                         /*

941                          * Force exit.

942                          */

943                         result = ISC_R_SUCCESS;

944                 }

945         } while (result != ISC_R_SUCCESS);

946 

947 #ifdef HAVE_LIBSCF

948         if (ns_smf_want_disable == 1) {

949                 result = ns_smf_get_instance(&instance, 1, ns_g_mctx);

950                 if (result == ISC_R_SUCCESS && instance != NULL) {

951                         if (smf_disable_instance(instance, 0) != 0)

952                                 UNEXPECTED_ERROR(__FILE__, __LINE__,

953                                                  "smf_disable_instance() "

954                                                  "failed for %s : %s",

955                                                  instance,

956                                                  scf_strerror(scf_error()));

957                 }

958                 if (instance != NULL)

959                         isc_mem_free(ns_g_mctx, instance);

960         }

961 #endif /* HAVE_LIBSCF */

962 

963         cleanup();

964 

965         if (want_stats) {

966                 isc_mem_stats(ns_g_mctx, stdout);

967                 isc_mutex_stats(stdout);

968         }

969 

970         if (ns_g_memstatistics && memstats != NULL) {

971                 FILE *fp = NULL;

972                 result = isc_stdio_open(memstats, "w", &fp);

973                 if (result == ISC_R_SUCCESS) {

974                         isc_mem_stats(ns_g_mctx, fp);

975                         isc_mutex_stats(fp);

976                         isc_stdio_close(fp);

977                 }

978         }

979         isc_mem_destroy(&ns_g_mctx);

980         isc_mem_checkdestroyed(stderr);

981 

982         ns_main_setmemstats(NULL);

983 

984         isc_app_finish();

985 

986         ns_os_closedevnull();

987 

988         ns_os_shutdown();

989 

990         return (0);

991 }

 

 

 

三、 初始设置setup

595         ns_os_tzset(); 初始化时区

596 

597         ns_os_opendevnull(); 打开空设备以便消息转向

 

599 #ifdef HAVE_LIBSCF 是否solaris的smf管理机制

600         /* Check if named is under smf control, before chroot. */

601         result = ns_smf_get_instance(&instance, 0, ns_g_mctx);

602         /* We don't care about instance, just check if we got one. */

603         if (result == ISC_R_SUCCESS)

604                 ns_smf_got_instance = 1;

605         else

606                 ns_smf_got_instance = 0;

607         if (instance != NULL)

608                 isc_mem_free(ns_g_mctx, instance);

609 #endif /* HAVE_LIBSCF */

如果是chroot运行方式化,初始化可用资源。Chroot是以普通用户运行超级资源,是unix系统的一种机制

611 #ifdef PATH_RANDOMDEV

612         /*

613          * Initialize system's random device as fallback entropy source

614          * if running chroot'ed.

615          */

616         if (ns_g_chrootdir != NULL) {

617                 result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy);

618                 if (result != ISC_R_SUCCESS)

619                         ns_main_earlyfatal("isc_entropy_create() failed: %s",

620                                            isc_result_totext(result));

621 

622                 result = isc_entropy_createfilesource(ns_g_fallbackentropy,

623                                                       PATH_RANDOMDEV);

624                 if (result != ISC_R_SUCCESS) {

625                         ns_main_earlywarning("could not open pre-chroot "

626                                              "entropy source %s: %s",

627                                              PATH_RANDOMDEV,

628                                              isc_result_totext(result));

629                         isc_entropy_detach(&ns_g_fallbackentropy);

630                 }

631         }

632 #endif

看cpu数目

634 #ifdef ISC_PLATFORM_USETHREADS

635         /*

636          * Check for the number of cpu's before ns_os_chroot().

637          */

638         ns_g_cpus_detected = isc_os_ncpus();

639 #endif

以下说明了最小权限运行机制,读config文件需要有root机制,通过unix的sid置位实现,即setsid()

/*

644          * For operating systems which have a capability mechanism, now

645          * is the time to switch to minimal privs and change our user id.

646          * On traditional UNIX systems, this call will be a no-op, and we

647          * will change the user ID after reading the config file the first

648          * time.  (We need to read the config file to know which possibly

649          * privileged ports to bind() to.)

650          */

651         ns_os_minprivs();

652 日志初始化

653         result = ns_log_init(ISC_TF(ns_g_username != NULL));

654         if (result != ISC_R_SUCCESS)

655                 ns_main_earlyfatal("ns_log_init() failed: %s",

656                                    isc_result_totext(result));

 

pid = fork();产生新的子进程,如果是直接named而不是named –g的话,因此,需要派生子进程,并关闭父的一些输入输出句柄,参见fork例程

if (!ns_g_foreground)

666                 ns_os_daemonize();

/*

669          * We call isc_app_start() here as some versions of FreeBSD's fork()

670          * destroys all the signal handling it sets up.

671          */

Isc_app_start主要是处理fork的信号机制的恢复

672         result = isc_app_start();

673         if (result != ISC_R_SUCCESS)

674                 ns_main_earlyfatal("isc_app_start() failed: %s",

675                                    isc_result_totext(result));

676 写日志文件,开始启动

677         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,

678                       ISC_LOG_NOTICE, "starting BIND %s%s", ns_g_version,

679                       saved_command_line);

680 

681         isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,

682                       ISC_LOG_NOTICE, "built with %s", ns_g_configargs);

683 

接下来是资源限制部分,可用#ulimit –a来理解

  /*

729          * Record the server's startup time.

730          */

731         result = isc_time_now(&ns_g_boottime);

732         if (result != ISC_R_SUCCESS)

733                 ns_main_earlyfatal("isc_time_now() failed: %s",

734                                    isc_result_totext(result));

735 

生成管理器,如任务、超时、entropy、hash,socket等管理器

736         result = create_managers();

737         if (result != ISC_R_SUCCESS)

738                 ns_main_earlyfatal("create_managers() failed: %s",

739                                    isc_result_totext(result));

740 

741         ns_builtin_init();

742 

743         /*

744          * Add calls to register sdb drivers here.

745          */

746         /* xxdb_init(); */

747 

748 #ifdef DLZ

749         /*

750          * Registyer any DLZ drivers.

751          */

752         result = dlz_drivers_init();

753         if (result != ISC_R_SUCCESS)

754                 ns_main_earlyfatal("dlz_drivers_init() failed: %s",

755                                    isc_result_totext(result));

756 #endif

757 

生成服务,重要部分,见分析六

758         ns_server_create(ns_g_mctx, &ns_g_server);

759 }

760 

 

 

 

四、 运行主体程序

文件http://202.120.16.5/lxr/http/source/lib/isc/unix/app.c#L431

 

430 isc_result_t

431 isc_app_run(void) {

432         int result;

433         isc_event_t *event, *next_event;

434         isc_task_t *task;

435 #ifdef ISC_PLATFORM_USETHREADS

436         sigset_t sset;

437         char strbuf[ISC_STRERRORSIZE];

438 #ifdef HAVE_SIGWAIT

439         int sig;

440 #endif

441 #endif /* ISC_PLATFORM_USETHREADS */

442 

443 #ifdef HAVE_LINUXTHREADS 如果启用了多线程编译,目前我们编译的是单线程,可用ps –em|grep named查看线程数

444         REQUIRE(main_thread == pthread_self());

445 #endif

446 加锁,事件队列是关键区,race condition

447         LOCK(&lock);

448 

449         if (!running) {

450                 running = ISC_TRUE;

451 事件结构有sender,type,action,arguments,而采用队列ev_link实现,事件FIFO依序处理。

 

 

 

452                 /*

453                  * Post any on-run events (in FIFO order).

454                  */主循环

455                 for (event = ISC_LIST_HEAD(on_run);

456                      event != NULL;

457                      event = next_event) {

458                         next_event = ISC_LIST_NEXT(event, ev_link);

459                         ISC_LIST_UNLINK(on_run, event, ev_link);

460                         task = event->ev_sender;

461                         event->ev_sender = NULL;

事件任务机制,见分析五

462                         isc_task_sendanddetach(&task, &event);

463                 }

464 

465         }

466 

467         UNLOCK(&lock);

468 以下主要为信号捕获处理机制,特别注意shutdown退出时的处理。信号catch处理机制能够使应用更安全退出。

469 #ifndef HAVE_SIGWAIT

470         /*

471          * Catch SIGHUP.

472          *

473          * We do this here to ensure that the signal handler is installed

474          * (i.e. that it wasn't a "one-shot" handler).

475          */

476         result = handle_signal(SIGHUP, reload_action);

477         if (result != ISC_R_SUCCESS)

478                 return (ISC_R_SUCCESS);

479 #endif

480 

481 #ifdef ISC_PLATFORM_USETHREADS

482         /*

483          * There is no danger if isc_app_shutdown() is called before we wait

484          * for signals.  Signals are blocked, so any such signal will simply

485          * be made pending and we will get it when we call sigwait().

486          */

487 

488         while (!want_shutdown) {

489 #ifdef HAVE_SIGWAIT

490                 /*

491                  * Wait for SIGHUP, SIGINT, or SIGTERM.

492                  */

493                 if (sigemptyset(&sset) != 0 ||

494                     sigaddset(&sset, SIGHUP) != 0 ||

495                     sigaddset(&sset, SIGINT) != 0 ||

496                     sigaddset(&sset, SIGTERM) != 0) {

497                         isc__strerror(errno, strbuf, sizeof(strbuf));

498                         UNEXPECTED_ERROR(__FILE__, __LINE__,

499                                          "isc_app_run() sigsetops: %s", strbuf);

500                         return (ISC_R_UNEXPECTED);

501                 }

502 

503 #ifndef HAVE_UNIXWARE_SIGWAIT

504                 result = sigwait(&sset, &sig);

505                 if (result == 0) {

506                         if (sig == SIGINT ||

507                             sig == SIGTERM)

508                                 want_shutdown = ISC_TRUE;

509                         else if (sig == SIGHUP)

510                                 want_reload = ISC_TRUE;

511                 }

512 

513 #else /* Using UnixWare sigwait semantics. */

514                 sig = sigwait(&sset);

515                 if (sig >= 0) {

516                         if (sig == SIGINT ||

517                             sig == SIGTERM)

518                                 want_shutdown = ISC_TRUE;

519                         else if (sig == SIGHUP)

520                                 want_reload = ISC_TRUE;

521                 }

522 

523 #endif /* HAVE_UNIXWARE_SIGWAIT */

524 #else  /* Don't have sigwait(). */

525                 /*

526                  * Listen for all signals.

527                  */

528                 if (sigemptyset(&sset) != 0) {

529                         isc__strerror(errno, strbuf, sizeof(strbuf));

530                         UNEXPECTED_ERROR(__FILE__, __LINE__,

531                                          "isc_app_run() sigsetops: %s", strbuf);

532                         return (ISC_R_UNEXPECTED);

533                 }

534                 result = sigsuspend(&sset);

535 #endif /* HAVE_SIGWAIT */

536 

537                 if (want_reload) {

538                         want_reload = ISC_FALSE;

539                         return (ISC_R_RELOAD);

540                 }

541 

542                 if (want_shutdown && blocked)

543                         exit(1);

544         }

545 

546 #else /* ISC_PLATFORM_USETHREADS */

547 

548         (void)isc__taskmgr_dispatch();

549 

550         result = evloop();

551         if (result != ISC_R_SUCCESS)

552                 return (result);

553 

554 #endif /* ISC_PLATFORM_USETHREADS */

555 

556         return (ISC_R_SUCCESS);

557 }

 

正常关闭时,需要将相关线程也中止

558 

559 isc_result_t

560 isc_app_shutdown(void) {

561         isc_boolean_t want_kill = ISC_TRUE;

562         char strbuf[ISC_STRERRORSIZE];

563 

564         LOCK(&lock);

565 

566         REQUIRE(running);

567 

568         if (shutdown_requested)

569                 want_kill = ISC_FALSE;

570         else

571                 shutdown_requested = ISC_TRUE;

572 

573         UNLOCK(&lock);

574 

575         if (want_kill) {

576 #ifdef HAVE_LINUXTHREADS

577                 int result;

578 

579                 result = pthread_kill(main_thread, SIGTERM);

580                 if (result != 0) {

581                         isc__strerror(result, strbuf, sizeof(strbuf));

582                         UNEXPECTED_ERROR(__FILE__, __LINE__,

583                                          "isc_app_shutdown() pthread_kill: %s",

584                                          strbuf);

585                         return (ISC_R_UNEXPECTED);

586                 }

587 #else

588                 if (kill(getpid(), SIGTERM) < 0) {

589                         isc__strerror(errno, strbuf, sizeof(strbuf));

590                         UNEXPECTED_ERROR(__FILE__, __LINE__,

591                                          "isc_app_shutdown() kill: %s", strbuf);

592                         return (ISC_R_UNEXPECTED);

593                 }

594 #endif

595         }

596 

597         return (ISC_R_SUCCESS);

598 }

599 

 

五、 事件与任务处理

还没有充分看代码,需要进一步看代码,主要参考文件去理解app.c和Task.c去理解http://202.120.16.5/lxr/http/source/lib/isc/unix/app.c#L303

 

 

 

task = event->ev_sender;

event->ev_sender = NULL;

 

isc_task_sendanddetach(&task, &event);

void

430 isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {

431         isc_boolean_t idle1, idle2;

432         isc_task_t *task;

433 

434         /*

435          * Send '*event' to '*taskp' and then detach '*taskp' from its

436          * task.

437          */

438 

439         REQUIRE(taskp != NULL);

440         task = *taskp;

441         REQUIRE(VALID_TASK(task));

442 

443         XTRACE("isc_task_sendanddetach");

444 

445         LOCK(&task->lock);

446         idle1 = task_send(task, eventp);

447         idle2 = task_detach(task);

448         UNLOCK(&task->lock);

449 

450         /*

451          * If idle1, then idle2 shouldn't be true as well since we're holding

452          * the task lock, and thus the task cannot switch from ready back to

453          * idle.

454          */

455         INSIST(!(idle1 && idle2));

456 

457         if (idle1 || idle2)

458                 task_ready(task);

459 

460         *taskp = NULL;

461 }

462 

463 #define PURGE_OK(event) (((event)->ev_attributes & ISC_EVENTATTR_NOPURGE) == 0)

464 

 

 

六 服务任务生成(主要与rndcchannel通信)

3826 void

3827 ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {

3828         isc_result_t result;

3829 

3830         ns_server_t *server = isc_mem_get(mctx, sizeof(*server));

3831         if (server == NULL)

3832                 fatal("allocating server object", ISC_R_NOMEMORY);

3833 

3834         server->mctx = mctx;

3835         server->task = NULL;

3836 

3837         /* Initialize configuration data with default values. */

3838 

3839         result = isc_quota_init(&server->xfroutquota, 10);

3840         RUNTIME_CHECK(result == ISC_R_SUCCESS);

3841         result = isc_quota_init(&server->tcpquota, 10);

3842         RUNTIME_CHECK(result == ISC_R_SUCCESS);

3843         result = isc_quota_init(&server->recursionquota, 100);

3844         RUNTIME_CHECK(result == ISC_R_SUCCESS);

3845 

3846         result = dns_aclenv_init(mctx, &server->aclenv);

3847         RUNTIME_CHECK(result == ISC_R_SUCCESS);

3848 

3849         /* Initialize server data structures. */

3850         server->zonemgr = NULL; 区管理器

3851         server->interfacemgr = NULL;接口管理器

3852         ISC_LIST_INIT(server->viewlist);

3853         server->in_roothints = NULL;

3854         server->blackholeacl = NULL; 服务的ACL机制

3855 

3856         CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,

3857                                      &server->in_roothints),

3858                    "setting up root hints");

3859 

3860         CHECKFATAL(isc_mutex_init(&server->reload_event_lock),

3861                    "initializing reload event lock");

 绑定reload事件处理

3862         server->reload_event =   

3863                 isc_event_allocate(ns_g_mctx, server,

3864                                    NS_EVENT_RELOAD,

3865                                    ns_server_reload,

3866                                    server,

3867                                    sizeof(isc_event_t));

3868         CHECKFATAL(server->reload_event == NULL ?

3869                    ISC_R_NOMEMORY : ISC_R_SUCCESS,

3870                    "allocating reload event");

3871 

3872         CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY), 加密机制dst hmac

3873                    "initializing DST");

3874 TKEY加密管理

3875         server->tkeyctx = NULL;

3876         CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,

3877                                       &server->tkeyctx),

3878                    "creating TKEY context");

3879 

3880         /*

3881          * Setup the server task, which is responsible for coordinating

3882          * startup and shutdown of the server.

3883          */

生成服务器的任务机制

3884         CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),

3885                    "creating server task");

3886         isc_task_setname(server->task, "server", server);

3887         CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),

3888                    "isc_task_onshutdown");

3889         CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),

3890                    "isc_app_onrun");

3891 

3892         server->interface_timer = NULL; 接口保活

3893         server->heartbeat_timer = NULL; 心跳定时器

3894         server->pps_timer = NULL; 

3895 

3896         server->interface_interval = 0;

3897         server->heartbeat_interval = 0;

3898 生成区管理器

3899         CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,

3900                                       ns_g_socketmgr, &server->zonemgr),

3901                    "dns_zonemgr_create");

3902 统计文件,注意有以下统计信息:opcode,zone,resolver,receive query等

3903         server->statsfile = isc_mem_strdup(server->mctx, "named.stats");

3904         CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,

3905                    "isc_mem_strdup");

3906         server->nsstats = NULL;

3907         server->rcvquerystats = NULL;

3908         server->opcodestats = NULL;

3909         server->zonestats = NULL;

3910         server->resolverstats = NULL;

3911 转储文件

3912         server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");

3913         CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,

3914                    "isc_mem_strdup");

3915 递归文件

3916         server->recfile = isc_mem_strdup(server->mctx, "named.recursing");

3917         CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,

3918                    "isc_mem_strdup");

3919 

3920         server->hostname_set = ISC_FALSE;

3921         server->hostname = NULL;

3922         server->version_set = ISC_FALSE;

3923         server->version = NULL;

3924         server->server_usehostname = ISC_FALSE;

3925         server->server_id = NULL;

3926 

以下处理统计信息收集

3927         CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->nsstats,

3928                                            dns_nsstatscounter_max),

3929                    "dns_stats_create (server)");

3930 

3931         CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx,

3932                                              &server->rcvquerystats),

3933                    "dns_stats_create (rcvquery)");

3934 

3935         CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats),

3936                    "dns_stats_create (opcode)");

3937 

3938         CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->zonestats,

3939                                            dns_zonestatscounter_max),

3940                    "dns_stats_create (zone)");

3941 

3942         CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->resolverstats,

3943                                            dns_resstatscounter_max),

3944                    "dns_stats_create (resolver)");

3945 

3946         server->flushonshutdown = ISC_FALSE;

默认查询日志是关闭的,打开查询日志较大地影响解析性能

3947         server->log_queries = ISC_FALSE;

3948 

3949         server->controls = NULL;

3950         CHECKFATAL(ns_controls_create(server, &server->controls),

3951                    "ns_controls_create");

3952         server->dispatchgen = 0;

3953         ISC_LIST_INIT(server->dispatches);

3954 

3955         ISC_LIST_INIT(server->statschannels);

3956 

3957         server->magic = NS_SERVER_MAGIC;

3958         *serverp = server;

3959 }

3960 

 

附录:

事件结构:

80 struct isc_event {

 81         ISC_EVENT_COMMON(struct isc_event);

34 #define ISC_EVENT_COMMON(ltype)         \

 35         size_t                          ev_size; \

 36         unsigned int                    ev_attributes; \

 37         void *                          ev_tag; \

 38         isc_eventtype_t                 ev_type; \

 39         isc_taskaction_t                ev_action; \

 40         void *                          ev_arg; \

 41         void *                          ev_sender; \

 42         isc_eventdestructor_t           ev_destroy; \

 43         void *                          ev_destroy_arg; \

 44         ISC_LINK(ltype)                 ev_link

 

 

任务结构:

http://202.120.16.5/lxr/http/source/lib/isc/task.c#L78

 

78 struct isc_task {

 79         /* Not locked. */

 80         unsigned int                    magic;

 81         isc_taskmgr_t *                 manager;

 82         isc_mutex_t                     lock;

 83         /* Locked by task lock. */

 84         task_state_t                    state;

 85         unsigned int                    references;

 86         isc_eventlist_t                 events;

 87         isc_eventlist_t                 on_shutdown;

 88         unsigned int                    quantum;

 89         unsigned int                    flags;

 90         isc_stdtime_t                   now;

 91         char                            name[16];

 92         void *                          tag;

 93         /* Locked by task manager lock. */

 94         LINK(isc_task_t)                link;

 95         LINK(isc_task_t)                ready_link;

 96 };

 97 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值