【模拟电路实战】从零构建2KHz信号发生器:555与运放协同设计

核心内容摘要

检测结果为空?可能是这几个设置出了问题
工业企业数据治理“三区一循环”全景架构白皮书

Unity ARFoundation实战:如何用2D图像检测打造互动式AR名片(附完整代码)

文章目录事件循环线程事件循环相关源码文件事件主循环机制睡眠钩子Hooks机制睡眠钩子的实现Epoll 实战键盘输入监听事件循环线程众所周知Redis 服务器启动时会开启六个线程Thread-1 [redis-server]主线程Thread-2 [bio_close_file]后台 I/O 线程 - 文件关闭Thread-3 [bio_aof]后台 I/O 线程 - AOF 刷盘Thread-4 [bio_lazy_free]后台 I/O 线程 - 惰性删除Thread-5 [jemalloc_bg_thd]内存整理线程Thread-6 [jemalloc_bg_thd]内存整理线程而事件循环则位于Thread-1 [redis-server]主线程中。

事件循环相关源码文件源码文件说明ae.c事件驱动循环核心ae_epoll.cLinux 系统实现epollae_evport.cSolaris 专用ae_kqueue.cmacOS 专用ae_select.c老旧 Linux 或兼容模式使用ebuckets.c事件桶管理eventnotifier.c事件通讯器事件主循环机制Redis 的事件主循环位于ae.c中核心代码如下voidaeMain(aeEventLoop*eventLoop){eventLoop-stop0;while(!eventLoop-stop){aeProcessEvents(eventLoop,AE_ALL_EVENTS|AE_CALL_BEFORE_SLEEP|AE_CALL_AFTER_SLEEP);}}但死循环非常消耗 CPURedis 是如何让线程进入睡眠等待的呢真正的“睡眠”发生在aeApiPoll中其核心是调用系统epoll_waitstaticintaeApiPoll(aeEventLoop*eventLoop,structtimeval*tvp){aeApiState*stateeventLoop-apidata;intretval,numevents0;retvalepoll_wait(state-epfd,state-events,eventLoop-setsize,tvp?(tvp-tv_sec*1000(tvp-tv_usec

/

:-

;if(retval

{intj;numeventsretval;for(j0;jnumevents;j){intmask0;structepoll_event*estate-eventsj;if(e-eventsEPOLLIN)mask|AE_READABLE;if(e-eventsEPOLLOUT)mask|AE_WRITABLE;if(e-eventsEPOLLERR)mask|AE_WRITABLE|AE_READABLE;if(e-eventsEPOLLHUP)mask|AE_WRITABLE|AE_READABLE;eventLoop-fired[j].fde-data.fd;eventLoop-fired[j].maskmask;}}elseif(retval-1errno!EINTR){panic(aeApiPoll: epoll_wait, %s,strerror(errno));}returnnumevents;}epoll_wait就是实现“睡眠”的系统调用。

当没有事件时线程在此阻塞不消耗 CPU。

睡眠钩子Hooks机制为了在睡眠前后执行必要逻辑Redis 提供了钩子函数。

在initServer函数中注册aeSetBeforeSleepProc(server.el, beforeSleep); aeSetAfterSleepProc(server.el, afterSleep);在aeProcessEvents中调用if (eventLoop-beforesleep ! NULL (flags AE_CALL_BEFORE_SLEEP)) eventLoop-beforesleep(eventLoop); if (eventLoop-aftersleep ! NULL flags AE_CALL_AFTER_SLEEP) eventLoop-aftersleep(eventLoop);作用beforeSleep处理客户端写回、检查阻塞超时、计算下一次epoll_wait的超时时间等。

afterSleep清理或重置休眠期间的状态。

这些钩子避免了无限循环中 CPU 空转是 Redis 高效的核心之一。

睡眠钩子的实现beforeSleep钩子和afterSleep钩子的实现都在server.c中分别是void beforeSleep(struct aeEventLoop *eventLoop)和void afterSleep(struct aeEventLoop *eventLoop)。

实现上beforeSleep远比afterSleep复杂。

Epoll 实战键盘输入监听我们可以编写代码练习epoll的使用模拟 Redis 的事件监听机制。

#includestdio.h#includestdlib.h#includesys/epoll.h#includeunistd.h// 简单的错误处理宏#definepanic(fmt,...)\do{fprintf(stderr,FATAL ERROR: fmt (%s:%d)\n,##__VA_ARGS__,__FILE__,__LINE__);\exit(

;}while(

typedefstructepoll_eventEvent;intmain(void){intepfdepoll_create(

;if(epfd

{panic(epoll_create);return1;}// 设置监听标准输入键盘Event ev;ev.eventsEPOLLIN;ev.data.fdSTDIN_FILENO;if(epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,ev)

{panic(epoll_ctl);return1;}Event events[10];charbuf[1024];// 事件循环for(;;){intnfdsepoll_wait(epfd,events,10,-

;if(nfds

{panic(epoll_wait);return1;}// 处理就绪事件for(inti0;infds;i){if(events[i].data.fdSTDIN_FILENO){intnreadread(STDIN_FILENO,buf,sizeof(buf));if(nread

{buf[nread]\0;printf(键盘输入: %s,buf);}}}}close(epfd);return0;}编译运行gcc epoll_test.c -o epoll_test ./epoll_test这个程序会在没有输入时“睡眠”输入内容按回车后被唤醒完美模拟了 Redis 的事件处理模型。

91无风险app下载-91无风险app下载应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123