乐于分享
好东西不私藏

libev库源码分析系列教程(十一)

libev库源码分析系列教程(十一)

源码分析mettle后门工具学习 所使用的依赖库

官网:http://securitytech.cc

  • libev Select/Poll/完成端口兼容实现深度解析

    1. 兼容层整体架构

    1.1 设计理念

    libev通过统一的Backend接口抽象,为不同平台提供select、poll和Windows完成端口(IOCP)的兼容实现,确保在缺乏现代事件通知机制的环境中仍能正常工作。

    1.2 核心兼容层设计

    /* ev_select.c/poll.c - 兼容层统一接口 */structcompat_backend{  intmaxfd;                   /* 当前最大fd */intfd_setsize;              /* fd集合大小 */fd_set*rfds;                /* 读事件集合 */fd_set*wfds;                /* 写事件集合 */fd_set*rfds_copy;           /* 读事件副本 */fd_set*wfds_copy;           /* 写事件副本 */structpollfd*pfds;         /* poll fd数组 */intpfds_count;              /* poll fd计数 */};/* Windows IOCP相关结构 */#ifdef_WIN32structiocp_backend{  HANDLEiocp_handle;          /* 完成端口句柄 */OVERLAPPED_ENTRY*entries;   /* 完成包数组 */ULONGentries_count;         /* 完成包数量 */SOCKET*sockets;             /* 套接字数组 */intsocket_count;            /* 套接字数量 */};#endif

    2. Select后端实现

    2.1 Select初始化与配置

    /* ev_select.c - select后端初始化 */staticvoidselect_init (EV_P_intflags) {  /* 获取系统限制 */select_maxfds=getdtablesize ();     /* 处理FD_SETSIZE限制 */if (select_maxfds>FD_SETSIZE)    select_maxfds=FD_SETSIZE;       /* 分配fd集合内存 */select_rfds=ev_malloc (sizeof (fd_set));  select_wfds=ev_malloc (sizeof (fd_set));  select_rfds_copy=ev_malloc (sizeof (fd_set));  select_wfds_copy=ev_malloc (sizeof (fd_set));     FD_ZERO (select_rfds);  FD_ZERO (select_wfds);     /* 设置backend函数指针 */backend_modify=select_modify;  backend_poll=select_poll;  backend_fudge=1e-6;  /* select需要时间修正 */}/* fd集合动态管理 */staticvoidselect_adjust_fds (EV_P) {  /* 确保fd不超过FD_SETSIZE限制 */if (select_maxfd >= FD_SETSIZE)     {      /* 清理超出范围的fd */for (intfd=FD_SETSIZEfd <= select_maxfd++fd)         {          if (FD_ISSET (fdselect_rfds))            FD_CLR (fdselect_rfds);          if (FD_ISSET (fdselect_wfds))            FD_CLR (fdselect_wfds);         }      select_maxfd=FD_SETSIZE-1;     } }

    2.2 Select事件管理

    /* ev_select.c - select事件控制 */staticvoidselect_modify (EV_P_intfdintoevintnev) {  /* 更新最大fd */if (nev&&fd>select_maxfd)    select_maxfd=fd;       /* 更新fd集合 */if (nev&EV_READ)    FD_SET (fdselect_rfds);  elseFD_CLR (fdselect_rfds);       if (nev&EV_WRITE)    FD_SET (fdselect_wfds);  elseFD_CLR (fdselect_wfds);       /* 清理超出范围的fd */select_adjust_fds (EV_A); }/* select轮询实现 */staticvoidselect_poll (EV_P_ev_tstamptimeout) {  structtimevaltv;     /* 准备fd集合副本 */memcpy (select_rfds_copyselect_rfdssizeof (fd_set));  memcpy (select_wfds_copyselect_wfdssizeof (fd_set));     /* 设置超时 */if (timeout >= 1e6)     {      tv.tv_sec=1e6;      tv.tv_usec=0;     }  elseif (timeout<1e-6)     {      tv.tv_sec=0;      tv.tv_usec=0;     }  else     {      tv.tv_sec= (long)timeout;      tv.tv_usec= (long)((timeout- (long)timeout*1e6);     }  /* 执行select调用 */intres=select (select_maxfd+1,                      select_rfds_copy,                      select_wfds_copy,                      0,                      &tv);  if (res<0)     {      if (errno==EBADF)        select_handle_ebadf (EV_A);      return;     }  /* 处理就绪事件 */if (res>0)    select_process_ready_fds (EV_A_res); }/* 处理就绪fd */staticvoidselect_process_ready_fds (EV_P_intready_count) {  intprocessed=0;     for (intfd=0fd <= select_maxfd&&processed<ready_count++fd)     {      intrevents=0;             if (FD_ISSET (fdselect_rfds_copy))        revents |= EV_READ;      if (FD_ISSET (fdselect_wfds_copy))        revents |= EV_WRITE;               if (revents)         {          fd_event (EV_A_fdrevents);          ++processed;         }     } }

    3. Poll后端实现

    3.1 Poll初始化与内存管理

    /* ev_poll.c - poll后端初始化 */staticvoidpoll_init (EV_P_intflags) {  pollidxs=ev_malloc (sizeof (int*anfdmax);     /* 初始化索引数组 */for (inti=0i<anfdmax++i)    pollidxs [i=-1;       /* 分配pollfd数组 */pollfds=ev_malloc (sizeof (structpollfd*anfdmax);  pollfdmax=0;     /* 设置backend函数指针 */backend_modify=poll_modify;  backend_poll=poll_poll;  backend_fudge=0.;  /* poll不需要时间修正 */}/* pollfd数组动态扩容 */staticvoidpoll_adjust_arrays (EV_P) {  if (anfdmax>pollfdmax)     {      intoldmax=pollfdmax;      pollfdmax=anfdmax;             pollfds=ev_realloc (pollfdssizeof (structpollfd*pollfdmax);      pollidxs=ev_realloc (pollidxssizeof (int*pollfdmax);             /* 初始化新分配的部分 */for (inti=oldmaxi<pollfdmax++i)         {          pollidxs [i=-1;          pollfds [i].fd=-1;          pollfds [i].events=0;          pollfds [i].revents=0;         }     } }

    3.2 Poll事件管理

    /* ev_poll.c - poll事件控制 */staticvoidpoll_modify (EV_P_intfdintoevintnev) {  intidx=pollidxs [fd];  intevents=0;     /* 转换事件类型 */if (nev&EV_READ)    events |= POLLIN;  if (nev&EV_WRITE)    events |= POLLOUT;       if (idx<0)  /* 新增fd */     {      if (nev)         {          idx=pollfdmax++;          pollidxs [fd=idx;          pollfds [idx].fd=fd;          pollfds [idx].events=events;          pollfds [idx].revents=0;         }     }  else/* 修改现有fd */     {      if (nev)         {          pollfds [idx].events=events;         }      else/* 删除fd */         {          /* 用最后一个元素填补空缺 */if (idx<--pollfdmax)             {              pollfds [idx=pollfds [pollfdmax];              pollidxs [pollfds [idx].fd=idx;             }          pollidxs [fd=-1;         }     } }/* poll轮询实现 */staticvoidpoll_poll (EV_P_ev_tstamptimeout) {  /* 调整数组大小 */poll_adjust_arrays (EV_A);     /* 执行poll调用 */intres=poll (pollfdspollfdmax,                    timeout >= 1e6 ? 1e6*1e3 :                    timeout<1e-6 ? 0 :                   (int)(timeout*1e3));  if (res<0)     {      if (errno==EBADF)        poll_handle_ebadf (EV_A);      return;     }  /* 处理返回事件 */if (res>0)    poll_process_events (EV_A_res); }/* 处理poll事件 */staticvoidpoll_process_events (EV_P_intevent_count) {  intprocessed=0;     for (inti=0i<pollfdmax&&processed<event_count++i)     {      structpollfd*pfd=&pollfds [i];             if (pfd->revents)         {          intrevents=0;                     if (pfd->revents& (POLLIN | POLLERR | POLLHUP))            revents |= EV_READ;          if (pfd->revents& (POLLOUT | POLLERR | POLLHUP))            revents |= EV_WRITE;          if (pfd->revents&POLLNVAL)            revents |= EV_ERROR;                       if (revents)             {              fd_event (EV_A_pfd->fdrevents);              ++processed;             }         }     } }

    4. Windows完成端口实现

    4.1 IOCP初始化与配置

    /* ev_win32.c - Windows完成端口初始化 */#ifdef_WIN32staticvoidiocp_init (EV_P_intflags) {  /* 创建完成端口 */iocp_handle=CreateIoCompletionPort (INVALID_HANDLE_VALUENULL00);  if (!iocp_handle)    return;       /* 分配完成包数组 */entries_count=256;  entries=malloc (sizeof (OVERLAPPED_ENTRY*entries_count);     /* 分配套接字数组 */socket_count=64;  sockets=malloc (sizeof (SOCKET*socket_count);     /* 设置backend函数指针 */backend_modify=iocp_modify;  backend_poll=iocp_poll;  backend_fudge=0.; }/* 套接字关联到完成端口 */staticintiocp_associate_socket (SOCKETs) {  if (CreateIoCompletionPort ((HANDLE)siocp_handle, (ULONG_PTR)s0))     {      /* 添加到套接字数组 */if (socket_count <= socket_registered)         {          socket_count *= 2;          sockets=realloc (socketssizeof (SOCKET*socket_count);         }      sockets [socket_registered++=s;      return0;     }  return-1; }#endif

    4.2 IOCP事件处理

    #ifdef_WIN32/* ev_win32.c - IOCP事件控制 */staticvoidiocp_modify (EV_P_intfdintoevintnev) {  SOCKETs= (SOCKET)fd;     if (!oev&&nev)  /* 新增套接字 */     {      iocp_associate_socket (s);     }  elseif (oev&& !nev)  /* 删除套接字 */     {      /* 从完成端口分离 */iocp_dissociate_socket (s);     }       /* 更新事件监听 */if (nev&EV_READ)    iocp_start_read (s);  if (nev&EV_WRITE)    iocp_start_write (s); }/* IOCP轮询实现 */staticvoidiocp_poll (EV_P_ev_tstamptimeout) {  ULONGnum_entries;  ULONGtimeout_ms=timeout >= 1e6 ? INFINITE :                     timeout<1e-6 ? 0 :                      (ULONG)(timeout*1e3);                        /* 等待完成包 */if (GetQueuedCompletionStatusEx (iocp_handleentriesentries_count,                                   &num_entriestimeout_ms, FALSE))     {      /* 处理完成事件 */for (ULONGi=0i<num_entries++i)         {          OVERLAPPED_ENTRY*entry=&entries[i];          SOCKETs= (SOCKET)entry->lpCompletionKey;          DWORDbytes_transferred=entry->dwNumberOfBytesTransferred;          LPOVERLAPPEDoverlapped=entry->lpOverlapped;                     /* 根据overlapped确定事件类型 */intrevents=iocp_overlapped_to_events (overlappedbytes_transferred);          fd_event (EV_A_ (int)srevents);         }     }  else     {      /* 处理错误 */DWORDerror=GetLastError ();      if (error!=WAIT_TIMEOUT)        iocp_handle_error (EV_A_error);     } }/* overlapped到事件类型转换 */staticintiocp_overlapped_to_events (LPOVERLAPPEDoverlappedDWORDbytes) {  intrevents=0;     /* 根据overlapped的使用方式判断事件类型 */if (overlapped==&read_overlapped)    revents |= EV_READ;  elseif (overlapped==&write_overlapped)    revents |= EV_WRITE;  elseif (overlapped==&accept_overlapped)    revents |= EV_READ;       /* 检查连接状态 */if (bytes==0)    revents |= EV_EOF;       returnrevents; }#endif

    5. 性能优化技术

    5.1 跨平台优化策略

    /* ev.c - 后端选择优化 */staticvoidchoose_best_backend (EV_P) {  /* 按性能优先级选择后端 */intbackend_priority[] = {#ifdefEV_USE_EPOLLEVPOLL,#endif#ifdefEV_USE_KQUEUEEVKQUEUE,#endif#ifdefEV_USE_PORTEVPORT,#endif#ifdefEV_USE_POLLEVPOLL,#endifEVSELECT/* fallback到select */   };     for (inti=0i<sizeof(backend_priority)/sizeof(backend_priority[0]); ++i)     {      if (backend_supported (backend_priority[i]))         {          backend=backend_priority[i];          break;         }     }}/* 后端性能特征检测 */staticintbackend_performance_score (intbackend_type) {  switch (backend_type)     {    caseEVPOLL:    return100;  /* 最高性能 */caseEVKQUEUE:  return95;   /* 高性能 */caseEVPORT:    return90;   /* 良好性能 */caseEVPOLL:    return70;   /* 中等性能 */caseEVSELECT:  return50;   /* 基础性能 */default:        return0;     } }

    5.2 内存使用优化

    /* ev_select.c - select内存优化 */staticvoidselect_optimize_memory (EV_P) {  /* 使用位图而非fd_set减少内存占用 */size_tbitmap_size= (select_maxfds+7) / 8;  uint8_t*read_bitmap=calloc (1bitmap_size);  uint8_t*write_bitmap=calloc (1bitmap_size);     /* 转换fd_set到位图 */for (intfd=0fd<select_maxfds++fd)     {      if (FD_ISSET (fdselect_rfds))        read_bitmap[fd >> 3] |= (1 << (fd&7));      if (FD_ISSET (fdselect_wfds))        write_bitmap[fd >> 3] |= (1 << (fd&7));     }       /* 使用位图进行快速查找 *//* ... 优化的事件检查逻辑 ... */}/* ev_poll.c - poll内存池管理 */staticstructpollfd*poll_get_cached_pfd (EV_P_intfd) {  /* 使用对象池避免频繁分配 */staticstructpollfdpfd_cache[1024];  staticintcache_index=0;     structpollfd*pfd=&pfd_cache[cache_index++];  if (cache_index >= 1024)    cache_index=0;       pfd->fd=fd;  pfd->events=0;  pfd->revents=0;     returnpfd; }

    6. 错误处理与兼容性

    6.1 跨平台错误处理

    /* ev.c - 统一错误处理 */staticvoidhandle_backend_error (EV_P_interror_code) {  switch (error_code)     {    caseEBADF:      /* fd无效,清理相关资源 */cleanup_invalid_fds (EV_A);      break;    caseEINVAL:      /* 参数错误,重新初始化后端 */reinitialize_backend (EV_A);      break;    caseEMFILE:      /* 文件描述符耗尽,降低资源使用 */reduce_resource_usage (EV_A);      break;    caseENOMEM:      /* 内存不足,使用更节省内存的策略 */switch_to_low_memory_mode (EV_A);      break;     } }/* 平台特定错误映射 */staticintmap_system_error (intsys_error) {#ifdef_WIN32switch (sys_error)     {    caseWSAEBADF:    returnEBADF;    caseWSAEINVAL:   returnEINVAL;    caseWSAEMFILE:   returnEMFILE;    caseWSAENOBUFS:  returnENOMEM;    default:          returnsys_error;     }#elsereturnsys_error;#endif}

    6.2 向后兼容性处理

    /* ev_select.c - 老版本select兼容 */staticvoidselect_legacy_compatibility (EV_P) {  /* 处理老系统select的限制 */#if defined(_AIX|| defined(__hpux)  /* AIX和HP-UX的select有特殊限制 */select_max_timeout=100;  /* 限制最大超时时间 */#endif#if defined(__sgi)  /* SGI IRIX的select行为特殊 */select_use_heartbeat=1;  /* 使用心跳机制 */#endif}/* ev_poll.c - poll兼容性处理 */staticvoidpoll_check_compatibility (EV_P) {  /* 检查poll实现质量 */structpollfdtest_pfd= { 0POLLIN0 };     /* 某些系统poll实现有bug */if (poll (&test_pfd10<0&&errno==EINVAL)     {      /* 切换到select后端 */backend=EVSELECT;      select_init (EV_A_0);     } }

    7. 调试与监控机制

    7.1 兼容层状态监控

    #ifEV_STATS/* ev_select.c - select统计信息 */VAR(unsigned long, select_calls, , , 0)          /* select调用次数 */VAR(unsigned long, select_ready_fds, , , 0)      /* 就绪fd总数 */VAR(ev_tstampselect_max_wait_time, , , 0.)     /* 最大等待时间 */VAR(unsigned long, select_fd_limit_hits, , , 0)  /* FD_SETSIZE限制触发次数 *//* ev_poll.c - poll统计信息 */VAR(unsigned long, poll_calls, , , 0)            /* poll调用次数 */VAR(unsigned long, poll_ready_events, , , 0)     /* 就绪事件总数 */VAR(unsigned long, poll_array_resizes, , , 0)    /* 数组重分配次数 */VAR(ev_tstamppoll_avg_wait_time, , , 0.)       /* 平均等待时间 */#endif/* 性能监控包装 */staticintselect_with_monitoring (EV_P_intnfdsfd_set*rfdsfd_set*wfds,                         fd_set*efdsstructtimeval*timeout) {#ifEV_STATSev_tstampstart_time=ev_time ();#endifintresult=select (nfdsrfdswfdsefdstimeout);#ifEV_STATSev_tstampelapsed=ev_time () -start_time;  ++select_calls;     if (result>0)    select_ready_fds+=result;       if (elapsed>select_max_wait_time)    select_max_wait_time=elapsed;       if (nfds >= FD_SETSIZE)    ++select_fd_limit_hits;#endifreturnresult; }

    7.2 调试诊断工具

    /* ev.c - 后端诊断信息 */staticvoiddump_backend_status (EV_P) {  fprintf (stderr"Backend Status:\n");  fprintf (stderr"  Type: %s\n"backend_name (backend));  fprintf (stderr"  Max FD: %d\n"anfdmax);  fprintf (stderr"  Active FDs: %d\n"activecnt);     switch (backend)     {    caseEVSELECT:      fprintf (stderr"  Select Max FD: %d\n"select_maxfd);      fprintf (stderr"  FD_SETSIZE Limit: %d\n"FD_SETSIZE);      break;    caseEVPOLL:      fprintf (stderr"  Poll FD Count: %d\n"pollfdmax);      break;#ifdef_WIN32caseEVIOCP:      fprintf (stderr"  IOCP Handle: %p\n"iocp_handle);      fprintf (stderr"  Registered Sockets: %d\n"socket_registered);      break;#endif     } }/* 运行时诊断接口 */voidev_backend_diagnose (EV_P) {#ifEV_DEBUGdump_backend_status (EV_A);  verify_backend_consistency (EV_A);#endif}

    8. 最佳实践与使用建议

    8.1 后端选择策略

    /* 1. 自动后端选择 */voidconfigure_automatic_backend (EV_P) {  /* 根据系统特性和负载自动选择最优后端 */if (running_on_linux () &&kernel_version () >= KERNEL_2_6)     {      backend=EVPOLL;  /* 优先使用epoll */     }  elseif (running_on_bsd ())     {      backend=EVKQUEUE;  /* BSD系统使用kqueue */     }  else     {      /* fallback策略 */backend=detect_best_available_backend ();     } }/* 2. 手动后端指定 */voidconfigure_specific_backend (EV_P_intdesired_backend) {  /* 强制使用指定后端 */if (backend_supported (desired_backend))     {      backend=desired_backend;      initialize_selected_backend (EV_A_0);     }  else     {      /* 指定后端不可用,使用默认选择 */choose_best_backend (EV_A);     } }

    8.2 性能调优建议

    /* 1. 高性能场景优化 */voidoptimize_for_high_performance (EV_P) {  /* 增大内部缓冲区 */if (backend==EVSELECT)     {      /* select场景下增大fd集合大小 */select_reserve_fds (EV_A_8192);     }  elseif (backend==EVPOLL)     {      /* poll场景下预分配更大数组 */poll_preallocate_arrays (EV_A_4096);     } }/* 2. 内存敏感场景 */voidoptimize_for_memory_efficiency (EV_P) {  /* 使用更节省内存的数据结构 */if (backend==EVSELECT)     {      /* 使用压缩的fd位图 */select_enable_bitmap_mode (EV_A);     }  elseif (backend==EVPOLL)     {      /* 使用稀疏数组 */poll_enable_sparse_arrays (EV_A);     } }/* 3. 兼容性优先场景 */voidoptimize_for_maximum_compatibility (EV_P) {  /* 选择最广泛支持的后端 */backend=EVSELECT;  /* select具有最好的兼容性 */select_init (EV_A_0);     /* 启用兼容性模式 */select_enable_legacy_mode (EV_A); }

    分析版本: v1.0源码版本: libev 4.33更新时间: 2026年3月1日

  • 公众号:安全狗的自我修养

  • vx:2207344074

  • http://gitee.com/haidragon

  • http://github.com/haidragon

  • bilibili:haidragonx

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » libev库源码分析系列教程(十一)

评论 抢沙发

4 + 2 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮