{"id":2698,"date":"2019-01-16T14:53:36","date_gmt":"2019-01-16T06:53:36","guid":{"rendered":"https:\/\/damogame.cn:15443\/wordpress\/?p=2698"},"modified":"2019-01-16T14:53:36","modified_gmt":"2019-01-16T06:53:36","slug":"linux-%e4%b8%8b%e5%ae%9a%e6%97%b6%e5%99%a8%e7%9a%84%e5%ae%9e%e7%8e%b0%e6%96%b9%e5%bc%8f%e5%88%86%e6%9e%90-2","status":"publish","type":"post","link":"https:\/\/i007.cc\/wordpress\/archives\/2698","title":{"rendered":"Linux \u4e0b\u5b9a\u65f6\u5668\u7684\u5b9e\u73b0\u65b9\u5f0f\u5206\u6790"},"content":{"rendered":"<div class=\"ibm-columns dw-article-topbar\">\n<div class=\"ibm-col-6-2 ibm-col-medium-6-4 ibm-col-small-6-2 dw-article-social\">\n<div id=\"dw-article-cmts\">\n<div class=\"dw-article-cmtslink\">\n<div id=\"nCmts\">\u6982\u8bba<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>\u5b9a\u65f6\u5668\u5c5e\u4e8e\u57fa\u672c\u7684\u57fa\u7840\u7ec4\u4ef6\uff0c\u4e0d\u7ba1\u662f\u7528\u6237\u7a7a\u95f4\u7684\u7a0b\u5e8f\u5f00\u53d1\uff0c\u8fd8\u662f\u5185\u6838\u7a7a\u95f4\u7684\u7a0b\u5e8f\u5f00\u53d1\uff0c\u5f88\u591a\u65f6\u5019\u90fd\u9700\u8981\u6709\u5b9a\u65f6\u5668\u4f5c\u4e3a\u57fa\u7840\u7ec4\u4ef6\u7684\u652f\u6301\uff0c\u4f46\u4f7f\u7528\u573a\u666f\u7684\u4e0d\u540c\uff0c\u5bf9\u5b9a\u65f6\u5668\u7684\u5b9e\u73b0\u8003\u8651\u4e5f\u4e0d\u5c3d\u76f8\u540c\uff0c\u672c\u6587\u8ba8\u8bba\u4e86\u5728 Linux \u73af\u5883\u4e0b\uff0c\u5e94\u7528\u5c42\u548c\u5185\u6838\u5c42\u7684\u5b9a\u65f6\u5668\u7684\u5404\u79cd\u5b9e\u73b0\u65b9\u6cd5\uff0c\u5e76\u5206\u6790\u4e86\u5404\u79cd\u5b9e\u73b0\u65b9\u6cd5\u7684\u5229\u5f0a\u4ee5\u53ca\u9002\u5b9c\u7684\u4f7f\u7528\u73af\u5883\u3002<\/p>\n<p>\u9996\u5148\uff0c\u7ed9\u51fa\u4e00\u4e2a\u57fa\u672c\u6a21\u578b\uff0c\u5b9a\u65f6\u5668\u7684\u5b9e\u73b0\uff0c\u9700\u8981\u5177\u5907\u4ee5\u4e0b\u51e0\u4e2a\u884c\u4e3a\uff0c\u8fd9\u4e5f\u662f\u5728\u540e\u9762\u8bc4\u5224\u5404\u79cd\u5b9a\u65f6\u5668\u5b9e\u73b0\u7684\u4e00\u4e2a\u57fa\u672c\u6a21\u578b [1]\uff1a<\/p>\n<p>StartTimer(Interval, TimerId, ExpiryAction)<\/p>\n<p>\u6ce8\u518c\u4e00\u4e2a\u65f6\u95f4\u95f4\u9694\u4e3a Interval \u540e\u6267\u884c ExpiryAction \u7684\u5b9a\u65f6\u5668\u5b9e\u4f8b\uff0c\u5176\u4e2d\uff0c\u8fd4\u56de TimerId \u4ee5\u533a\u5206\u5728\u5b9a\u65f6\u5668\u7cfb\u7edf\u4e2d\u7684\u5176\u4ed6\u5b9a\u65f6\u5668\u5b9e\u4f8b\u3002<\/p>\n<p>StopTimer(TimerId)<\/p>\n<p>\u6839\u636e TimerId \u627e\u5230\u6ce8\u518c\u7684\u5b9a\u65f6\u5668\u5b9e\u4f8b\u5e76\u6267\u884c Stop \u3002<\/p>\n<p>PerTickBookkeeping()<\/p>\n<p>\u5728\u4e00\u4e2a Tick \u5185\uff0c\u5b9a\u65f6\u5668\u7cfb\u7edf\u9700\u8981\u6267\u884c\u7684\u52a8\u4f5c\uff0c\u5b83\u6700\u4e3b\u8981\u7684\u884c\u4e3a\uff0c\u5c31\u662f\u68c0\u67e5\u5b9a\u65f6\u5668\u7cfb\u7edf\u4e2d\uff0c\u662f\u5426\u6709\u5b9a\u65f6\u5668\u5b9e\u4f8b\u5df2\u7ecf\u5230\u671f\u3002\u6ce8\u610f\uff0c\u8fd9\u91cc\u7684 Tick \u5b9e\u9645\u4e0a\u5df2\u7ecf\u9690\u542b\u4e86\u4e00\u4e2a\u65f6\u95f4\u7c92\u5ea6 (granularity) \u7684\u6982\u5ff5\u3002<\/p>\n<p>ExpiryProcessing()<\/p>\n<p>\u5728\u5b9a\u65f6\u5668\u5b9e\u4f8b\u5230\u671f\u4e4b\u540e\uff0c\u6267\u884c\u9884\u5148\u6ce8\u518c\u597d\u7684 ExpiryAction \u884c\u4e3a\u3002<\/p>\n<p>\u4e0a\u9762\u8bf4\u4e86\u57fa\u672c\u7684\u5b9a\u65f6\u5668\u6a21\u578b\uff0c\u4f46\u662f\u9488\u5bf9\u5b9e\u9645\u7684\u4f7f\u7528\u60c5\u51b5\uff0c\u53c8\u6709\u4ee5\u4e0b 2 \u79cd\u57fa\u672c\u884c\u4e3a\u7684\u5b9a\u65f6\u5668\uff1a<\/p>\n<p>Single-Shot Timer<\/p>\n<p>\u8fd9\u79cd\u5b9a\u65f6\u5668\uff0c\u4ece\u6ce8\u518c\u5230\u7ec8\u6b62\uff0c\u4ec5\u4ec5\u53ea\u6267\u884c\u4e00\u6b21\u3002<\/p>\n<p>Repeating Timer<\/p>\n<p>\u8fd9\u79cd\u5b9a\u65f6\u5668\uff0c\u5728\u6bcf\u6b21\u7ec8\u6b62\u4e4b\u540e\uff0c\u4f1a\u81ea\u52a8\u91cd\u65b0\u5f00\u59cb\u3002\u672c\u8d28\u4e0a\uff0c\u53ef\u4ee5\u8ba4\u4e3a Repeating Timer \u662f\u5728 Single-Shot Timer \u7ec8\u6b62\u4e4b\u540e\uff0c\u518d\u6b21\u6ce8\u518c\u5230\u5b9a\u65f6\u5668\u7cfb\u7edf\u91cc\u7684 Single-Shot Timer\uff0c\u56e0\u6b64\uff0c\u5728\u652f\u6301 Single-Shot Timer \u7684\u57fa\u7840\u4e0a\u652f\u6301 Repeating Timer \u5e76\u4e0d\u7b97\u7279\u522b\u7684\u590d\u6742\u3002<\/p>\n<h2 id=\"2\u57fa\u4e8e\u94fe\u8868\u548c\u4fe1\u53f7\u5b9e\u73b0\u5b9a\u65f6\u566824\u7248\u5185\u6838\u60c5\u51b5\u4e0boutline\" class=\"ibm-h2\">\u57fa\u4e8e\u94fe\u8868\u548c\u4fe1\u53f7\u5b9e\u73b0\u5b9a\u65f6\u5668 (2.4 \u7248\u5185\u6838\u60c5\u51b5\u4e0b )<\/h2>\n<p>\u5728 2.4 \u7684\u5185\u6838\u4e2d\uff0c\u5e76\u6ca1\u6709\u63d0\u4f9b POSIX timer \uff3b 2 \uff3d\u7684\u652f\u6301\uff0c\u8981\u5728\u8fdb\u7a0b\u73af\u5883\u4e2d\u652f\u6301\u591a\u4e2a\u5b9a\u65f6\u5668\uff0c\u53ea\u80fd\u81ea\u5df1\u6765\u5b9e\u73b0\uff0c\u597d\u5728 Linux \u63d0\u4f9b\u4e86 setitimer(2) \u7684\u63a5\u53e3\u3002\u5b83\u662f\u4e00\u4e2a\u5177\u6709\u95f4\u9694\u529f\u80fd\u7684\u5b9a\u65f6\u5668 (interval timer)\uff0c\u4f46\u5982\u679c\u60f3\u5728\u8fdb\u7a0b\u73af\u5883\u4e2d\u652f\u6301\u591a\u4e2a\u8ba1\u65f6\u5668\uff0c\u4e0d\u5f97\u4e0d\u81ea\u5df1\u6765\u7ba1\u7406\u6240\u6709\u7684\u8ba1\u65f6\u5668\u3002 setitimer(2) \u7684\u5b9a\u4e49\u5982\u4e0b\uff1a<\/p>\n<h5 id=\"N10071\" class=\"ibm-h5\">\u6e05\u5355 1. setitimer \u7684\u539f\u578b<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">#include &lt;sys\/time.h&gt;\r\n\r\n\u00a0int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);<\/pre>\n<p>&nbsp;<\/p>\n<p>setitimer \u80fd\u591f\u5728 Timer \u5230\u671f\u4e4b\u540e\uff0c\u81ea\u52a8\u518d\u6b21\u542f\u52a8\u81ea\u5df1\uff0c\u56e0\u6b64\uff0c\u7528\u5b83\u6765\u89e3\u51b3 Single-Shot Timer \u548c Repeating Timer \u7684\u95ee\u9898\u663e\u5f97\u5f88\u7b80\u5355\u3002\u8be5\u51fd\u6570\u53ef\u4ee5\u5de5\u4f5c\u4e8e 3 \u79cd\u6a21\u5f0f\uff1a<\/p>\n<p>ITIMER_REAL \u4ee5\u5b9e\u65f6\u65f6\u95f4 (real time) \u9012\u51cf\uff0c\u5728\u5230\u671f\u4e4b\u540e\u53d1\u9001 SIGALRM \u4fe1\u53f7<\/p>\n<p>ITIMER_VIRTUAL \u4ec5\u8fdb\u7a0b\u5728\u7528\u6237\u7a7a\u95f4\u6267\u884c\u65f6\u9012\u51cf\uff0c\u5728\u5230\u671f\u4e4b\u540e\u53d1\u9001 SIGVTALRM \u4fe1\u53f7<\/p>\n<p>ITIMER_PROF \u8fdb\u7a0b\u5728\u7528\u6237\u7a7a\u95f4\u6267\u884c\u4ee5\u53ca\u5185\u6838\u4e3a\u8be5\u8fdb\u7a0b\u670d\u52a1\u65f6 ( \u5178\u578b\u5982\u5b8c\u6210\u4e00\u4e2a\u7cfb\u7edf\u8c03\u7528 ) \u90fd\u4f1a\u9012\u51cf\uff0c\u4e0e ITIMER_VIRTUAL \u5171\u7528\u65f6\u53ef\u5ea6\u91cf\u8be5\u5e94\u7528\u5728\u5185\u6838\u7a7a\u95f4\u548c\u7528\u6237\u7a7a\u95f4\u7684\u65f6\u95f4\u6d88\u8017\u60c5\u51b5\uff0c\u5728\u5230\u671f\u4e4b\u540e\u53d1\u9001 SIGPROF \u4fe1\u53f7<\/p>\n<p>\u5b9a\u65f6\u5668\u7684\u503c\u7531\u4e0b\u9762\u7684\u7ed3\u6784\u5b9a\u4e49\uff1a<\/p>\n<h5 id=\"N10083\" class=\"ibm-h5\">\u6e05\u5355 2. setitimer \u5b9a\u65f6\u5668\u7684\u503c\u5b9a\u4e49<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">struct itimerval {\r\n\u00a0struct timeval it_interval; \/* next value *\/\r\n\u00a0struct timeval it_value;\u00a0\u00a0\u00a0\u00a0 \/* current value *\/\r\n\u00a0};\r\n\r\n\u00a0struct timeval {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0long tv_sec;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/* seconds *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0long tv_usec;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/* microseconds *\/ \r\n\u00a0};<\/pre>\n<p>&nbsp;<\/p>\n<p>setitimer() \u4ee5 new_value \u8bbe\u7f6e\u7279\u5b9a\u7684\u5b9a\u65f6\u5668\uff0c\u5982\u679c old_value \u975e\u7a7a\uff0c\u5219\u5b83\u8fd4\u56de which \u7c7b\u578b\u65f6\u95f4\u95f4\u9694\u5b9a\u65f6\u5668\u7684\u524d\u4e00\u4e2a\u503c\u3002\u5b9a\u65f6\u5668\u4ece it_value \u9012\u51cf\u5230\u96f6\uff0c\u7136\u540e\u4ea7\u751f\u4e00\u4e2a\u4fe1\u53f7\uff0c\u5e76\u91cd\u65b0\u8bbe\u7f6e\u4e3a it_interval\uff0c\u5982\u679c\u6b64\u65f6 it_interval \u4e3a\u96f6\uff0c\u5219\u8be5\u5b9a\u65f6\u5668\u505c\u6b62\u3002\u4efb\u4f55\u65f6\u5019\uff0c\u53ea\u8981 it_value \u8bbe\u7f6e\u4e3a\u96f6\uff0c\u8be5\u5b9a\u65f6\u5668\u5c31\u4f1a\u505c\u6b62\u3002<\/p>\n<p>\u7531\u4e8e setitimer() \u4e0d\u652f\u6301\u5728\u540c\u4e00\u8fdb\u7a0b\u4e2d\u540c\u65f6\u4f7f\u7528\u591a\u6b21\u4ee5\u652f\u6301\u591a\u4e2a\u5b9a\u65f6\u5668\uff0c\u56e0\u6b64\uff0c\u5982\u679c\u9700\u8981\u540c\u65f6\u652f\u6301\u591a\u4e2a\u5b9a\u65f6\u5b9e\u4f8b\u7684\u8bdd\uff0c\u9700\u8981\u7531\u5b9e\u73b0\u8005\u6765\u7ba1\u7406\u6240\u6709\u7684\u5b9e\u4f8b\u3002\u7528 setitimer() \u548c\u94fe\u8868\uff0c\u53ef\u4ee5\u6784\u9020\u4e00\u4e2a\u5728\u8fdb\u7a0b\u73af\u5883\u4e0b\u652f\u6301\u591a\u4e2a\u5b9a\u65f6\u5668\u5b9e\u4f8b\u7684 Timer\uff0c\u5728\u4e00\u822c\u7684\u5b9e\u73b0\u4e2d\u7684 PerTickBookkeeping \u65f6\uff0c\u4f1a\u9012\u589e\u6bcf\u4e2a\u5b9a\u65f6\u5668\u7684 elapse \u503c\uff0c\u76f4\u5230\u8be5\u503c\u9012\u589e\u5230\u6700\u521d\u8bbe\u5b9a\u7684 interval \u5219\u8868\u793a\u5b9a\u65f6\u5668\u5230\u671f\u3002<\/p>\n<p>\u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u5b9a\u65f6\u5668\u53ef\u4ee5\u5b9a\u4e49\u4e3a\uff1a<\/p>\n<h5 id=\"N10091\" class=\"ibm-h5\">\u6e05\u5355 3. \u57fa\u4e8e\u94fe\u8868\u7684\u5b9a\u65f6\u5668\u5b9a\u4e49<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">typedef int timer_id;\r\n\r\n\u00a0\/**\r\n\u00a0* The type of callback function to be called by timer scheduler when a timer\r\n\u00a0* has expired.\r\n\u00a0*\r\n\u00a0* @param id\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 The timer id.\r\n\u00a0* @param user_data\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 The user data.\r\n\u00a0* $param len\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 The length of user data.\r\n\u00a0*\/\r\n\u00a0typedef int timer_expiry(timer_id id, void *user_data, int len);\r\n\r\n\u00a0\/**\r\n\u00a0* The type of the timer\r\n\u00a0*\/\r\n\u00a0struct timer {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LIST_ENTRY(timer) entries;\/**&lt; list entry\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\/\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_id id;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; timer id\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\/\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int interval;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; timer interval(second) *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int elapse;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; 0 -&gt; interval\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\/\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_expiry *cb;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; call if expiry\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0void *user_data;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; callback arg\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int len;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; user_data length\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\/ \r\n\u00a0};<\/pre>\n<div class=\"ibm-syntax-container\">\n<div>\n<div id=\"highlighter_439103\" class=\"syntaxhighlighter  htmlscript\"><\/div>\n<\/div>\n<\/div>\n<p>\u5b9a\u65f6\u5668\u7684\u65f6\u95f4\u95f4\u9694\u4ee5 interval \u8868\u793a\uff0c\u800c elapse \u5219\u5728 PerTickBookkeeping() \u65f6\u9012\u589e\uff0c\u76f4\u5230 interval \u8868\u793a\u5b9a\u65f6\u5668\u4e2d\u6b62\uff0c\u6b64\u65f6\u8c03\u7528\u56de\u8c03\u51fd\u6570 cb \u6765\u6267\u884c\u76f8\u5173\u7684\u884c\u4e3a\uff0c\u800c user_data \u548c len \u4e3a\u7528\u6237\u53ef\u4ee5\u4f20\u9012\u7ed9\u56de\u8c03\u51fd\u6570\u7684\u53c2\u6570\u3002<\/p>\n<p>\u6240\u6709\u7684\u5b9a\u65f6\u5668\u5b9e\u4f8b\u4ee5\u94fe\u8868\u6765\u7ba1\u7406\uff1a<\/p>\n<h5 id=\"N1009D\" class=\"ibm-h5\">\u6e05\u5355 4. \u5b9a\u65f6\u5668\u94fe\u8868<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/**\r\n\u00a0* The timer list\r\n\u00a0*\/\r\n\u00a0struct timer_list {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LIST_HEAD(listheader, timer) header;\u00a0 \/**&lt; list header\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int num;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; timer entry number *\/ \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int max_num;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; max entry number\u00a0\u00a0\u00a0 *\/\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0void (*old_sigfunc)(int);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; save previous signal handler *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0void (*new_sigfunc)(int);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; our signal handler\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\/\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct itimerval ovalue;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; old timer value *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct itimerval value;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/**&lt; our internal timer value *\/\r\n\u00a0};<\/pre>\n<p>&nbsp;<\/p>\n<p>\u8fd9\u91cc\u5173\u4e8e\u94fe\u8868\u7684\u5b9e\u73b0\u4f7f\u7528\u4e86 BSD \u98ce\u683c\u5173\u4e8e\u94fe\u8868\u7684\u4e00\u7ec4\u5b8f\uff0c\u907f\u514d\u4e86\u518d\u9020\u8f6e\u5b50\uff1b\u8be5\u7ed3\u6784\u4e2d\uff0cold_sigfunc \u5728 init_timer \u521d\u59cb\u5b9a\u65f6\u5668\u94fe\u8868\u65f6\u5019\u7528\u6765\u4fdd\u5b58\u7cfb\u7edf\u5bf9 SIGALRM \u7684\u5904\u7406\u51fd\u6570\uff0c\u5728\u5b9a\u65f6\u5668\u7cfb\u7edf destory \u65f6\u7528\u6765\u6062\u590d\u5230\u4e4b\u524d\u7684\u5904\u7406\u51fd\u6570\uff1b ovalue \u7684\u7528\u9014\u4e0e\u6b64\u7c7b\u4f3c\u3002<\/p>\n<h5 id=\"N100A7\" class=\"ibm-h5\">\u6e05\u5355 5. \u5b9a\u65f6\u5668\u94fe\u8868\u7684\u521b\u5efa\u548c Destroy<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/**\r\n\u00a0* Create a timer list.\r\n\u00a0*\r\n\u00a0* @param count\u00a0 The maximum number of timer entries to be supported initially.\r\n\u00a0*\r\n\u00a0* @return\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0 means ok, the other means fail.\r\n\u00a0*\/\r\n\u00a0int init_timer(int count)\r\n\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int ret = 0;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if(count &lt;=0 || count &gt; MAX_TIMER_NUM) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0printf(\"the timer max number MUST less than %d.\\n\", MAX_TIMER_NUM); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return -1;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memset(&amp;timer_list, 0, sizeof(struct timer_list));\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LIST_INIT(&amp;timer_list.header);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_list.max_num = count;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/* Register our internal signal handler and store old signal handler *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if ((timer_list.old_sigfunc = signal(SIGALRM, sig_func)) == SIG_ERR) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return -1;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_list.new_sigfunc = sig_func;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\/*Setting our interval timer for driver our mutil-timer and store old timer value*\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_list.value.it_value.tv_sec = TIMER_START;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_list.value.it_value.tv_usec = 0;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_list.value.it_interval.tv_sec = TIMER_TICK;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_list.value.it_interval.tv_usec = 0;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ret = setitimer(ITIMER_REAL, &amp;timer_list.value, &amp;timer_list.ovalue);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return ret;\r\n\u00a0}\r\n\r\n\r\n\u00a0\/**\r\n\u00a0* Destroy the timer list.\r\n\u00a0*\r\n\u00a0* @return\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0 means ok, the other means fail.\r\n\u00a0*\/\r\n\u00a0int destroy_timer(void)\r\n\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct timer *node = NULL;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if ((signal(SIGALRM, timer_list.old_sigfunc)) == SIG_ERR) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return -1;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if((setitimer(ITIMER_REAL, &amp;timer_list.ovalue, &amp;timer_list.value)) &lt; 0) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return -1;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0while (!LIST_EMPTY(&amp;timer_list.header)) {\u00a0\u00a0\u00a0\u00a0 \/* Delete. *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0node = LIST_FIRST(&amp;timer_list.header);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0LIST_REMOVE(node, entries);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/* Free node *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0printf(\"Remove id %d\\n\", node-&gt;id);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0free(node-&gt;user_data);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0free(node);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memset(&amp;timer_list, 0, sizeof(struct timer_list));\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return 0;\r\n\u00a0}<\/pre>\n<p>&nbsp;<\/p>\n<p>\u6dfb\u52a0\u5b9a\u65f6\u5668\u7684\u52a8\u4f5c\u975e\u5e38\u7684\u7b80\u5355\uff0c\u672c\u8d28\u53ea\u662f\u4e00\u4e2a\u94fe\u8868\u7684\u63d2\u5165\u800c\u5df2\uff1a<\/p>\n<h5 id=\"N100B1\" class=\"ibm-h5\">\u6e05\u5355 6. \u5411\u5b9a\u65f6\u5668\u94fe\u8868\u4e2d\u6dfb\u52a0\u5b9a\u65f6\u5668<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/**\r\n\u00a0* Add a timer to timer list.\r\n\u00a0*\r\n\u00a0* @param interval\u00a0 The timer interval(second).\r\n\u00a0* @param cb\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 When cb!= NULL and timer expiry, call it.\r\n\u00a0* @param user_data Callback's param.\r\n\u00a0* @param len\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 The length of the user_data.\r\n\u00a0*\r\n\u00a0* @return\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 The timer ID, if == INVALID_TIMER_ID, add timer fail. \r\n\u00a0*\/\r\n\u00a0timer_id\u00a0 add_timer(int interval, timer_expiry *cb, void *user_data, int len)\r\n\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct timer *node = NULL;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (cb == NULL || interval &lt;= 0) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return INVALID_TIMER_ID;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0if(timer_list.num &lt; timer_list.max_num) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0timer_list.num++;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0} else {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return INVALID_TIMER_ID;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0if((node = malloc(sizeof(struct timer))) == NULL) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return INVALID_TIMER_ID;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0if(user_data != NULL || len != 0) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;user_data = malloc(len);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0memcpy(node-&gt;user_data, user_data, len);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;len = len;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;cb = cb;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;interval = interval;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;elapse = 0;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;id = timer_list.num;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0LIST_INSERT_HEAD(&amp;timer_list.header, node, entries);\r\n\r\n\u00a0\u00a0\u00a0\u00a0return node-&gt;id;\r\n\u00a0}<\/pre>\n<p>&nbsp;<\/p>\n<p>\u6ce8\u518c\u7684\u4fe1\u53f7\u5904\u7406\u51fd\u6570\u5219\u7528\u6765\u9a71\u52a8\u5b9a\u65f6\u5668\u7cfb\u7edf\uff1a<\/p>\n<h5 id=\"N100BB\" class=\"ibm-h5\">\u6e05\u5355 7. \u4fe1\u53f7\u5904\u7406\u51fd\u6570\u9a71\u52a8\u5b9a\u65f6\u5668<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/* Tick Bookkeeping *\/\r\n\u00a0static void sig_func(int signo)\r\n\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct timer *node = timer_list.header.lh_first;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for ( ; node != NULL; node = node-&gt;entries.le_next) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;elapse++;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if(node-&gt;elapse &gt;= node-&gt;interval) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;elapse = 0;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0node-&gt;cb(node-&gt;id, node-&gt;user_data, node-&gt;len); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0}<\/pre>\n<p>&nbsp;<\/p>\n<p>\u5b83\u4e3b\u8981\u662f\u5728\u6bcf\u6b21\u6536\u5230 SIGALRM \u4fe1\u53f7\u65f6\uff0c\u6267\u884c\u5b9a\u65f6\u5668\u94fe\u8868\u4e2d\u7684\u6bcf\u4e2a\u5b9a\u65f6\u5668 elapse \u7684\u81ea\u589e\u64cd\u4f5c\uff0c\u5e76\u4e0e interval \u76f8\u6bd4\u8f83\uff0c\u5982\u679c\u76f8\u7b49\uff0c\u4ee3\u8868\u6ce8\u518c\u7684\u5b9a\u65f6\u5668\u5df2\u7ecf\u8d85\u65f6\uff0c\u8fd9\u65f6\u5219\u8c03\u7528\u6ce8\u518c\u7684\u56de\u8c03\u51fd\u6570\u3002<\/p>\n<p>\u4e0a\u9762\u7684\u5b9e\u73b0\uff0c\u6709\u5f88\u591a\u53ef\u4ee5\u4f18\u5316\u7684\u5730\u65b9\uff1a\u8003\u8651\u53e6\u5916\u4e00\u79cd\u601d\u8def\uff0c\u5728\u5b9a\u65f6\u5668\u7cfb\u7edf\u5185\u90e8\u5c06\u7ef4\u62a4\u7684\u76f8\u5bf9 interval \u8f6c\u6362\u6210\u7edd\u5bf9\u65f6\u95f4\uff0c\u8fd9\u6837\uff0c\u5728\u6bcf PerTickBookkeeping \u65f6\uff0c\u53ea\u9700\u5c06\u5f53\u524d\u65f6\u95f4\u4e0e\u5b9a\u65f6\u5668\u7684\u7edd\u5bf9\u65f6\u95f4\u76f8\u6bd4\u8f83\uff0c\u5c31\u53ef\u4ee5\u77e5\u9053\u662f\u5426\u8be5\u5b9a\u65f6\u5668\u662f\u5426\u5230\u671f\u3002\u8fd9\u79cd\u65b9\u6cd5\uff0c\u628a\u9012\u589e\u64cd\u4f5c\u53d8\u4e3a\u4e86\u6bd4\u8f83\u64cd\u4f5c\u3002\u5e76\u4e14\u4e0a\u9762\u7684\u5b9e\u73b0\u65b9\u5f0f\uff0c\u6548\u7387\u4e5f\u4e0d\u9ad8\uff0c\u5728\u6267\u884c StartTimer\uff0cStopTimer\uff0cPerTickBookkeeping \u65f6\uff0c\u7b97\u6cd5\u590d\u6742\u5ea6\u5206\u522b\u4e3a O(1)\uff0cO(n)\uff0cO(n)\uff0c\u53ef\u4ee5\u5bf9\u4e0a\u9762\u7684\u5b9e\u73b0\u505a\u4e00\u4e2a\u7b80\u5355\u7684\u6539\u8fdb\uff0c\u5728 StartTimer \u65f6\uff0c\u5373\u5728\u6dfb\u52a0 Timer \u5b9e\u4f8b\u65f6\uff0c\u5bf9\u94fe\u8868\u8fdb\u884c\u6392\u5e8f\uff0c\u8fd9\u6837\u7684\u6539\u8fdb\uff0c\u53ef\u4ee5\u4f7f\u5f97\u5728\u6267\u884c StartTimer\uff0cStopTimer\uff0cPerTickBookkeeping \u65f6\uff0c\u7b97\u6cd5\u590d\u6742\u5ea6\u5206\u522b\u4e3a O(n)\uff0cO(1)\uff0cO(1) \u3002\u6539\u8fdb\u540e\u7684\u5b9a\u65f6\u5668\u7cfb\u7edf\u5982\u4e0b\u56fe 1\uff1a<\/p>\n<h5 id=\"N100C6\" class=\"ibm-h5\">\u56fe 1. \u57fa\u4e8e\u6392\u5e8f\u94fe\u8868\u7684\u5b9a\u65f6\u5668<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"ibm-downsize\" src=\"https:\/\/www.ibm.com\/developerworks\/cn\/linux\/l-cn-timers\/image001.jpg\" alt=\"\u57fa\u4e8e\u6392\u5e8f\u94fe\u8868\u7684\u5b9a\u65f6\u5668\" width=\"554\" height=\"78\" \/><\/p>\n<h2 id=\"3\u57fa\u4e8e26\u7248\u672c\u5185\u6838\u5b9a\u65f6\u5668\u7684\u5b9e\u73b0Posix\u5b9e\u65f6\u5b9a\u65f6\u5668outline\" class=\"ibm-h2\">\u57fa\u4e8e 2.6 \u7248\u672c\u5185\u6838\u5b9a\u65f6\u5668\u7684\u5b9e\u73b0 (Posix \u5b9e\u65f6\u5b9a\u65f6\u5668 )<\/h2>\n<p>Linux \u81ea 2.6 \u5f00\u59cb\uff0c\u5df2\u7ecf\u5f00\u59cb\u652f\u6301 POSIX timer \uff3b 2 \uff3d\u6240\u5b9a\u4e49\u7684\u5b9a\u65f6\u5668\uff0c\u5b83\u4e3b\u8981\u7531\u4e0b\u9762\u7684\u63a5\u53e3\u6784\u6210 :<\/p>\n<h5 id=\"N100D8\" class=\"ibm-h5\">\u6e05\u5355 8. POSIX timer \u63a5\u53e3<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">#include &lt;signal.h&gt;\r\n\u00a0#include &lt;time.h&gt;\r\n\r\n\u00a0int timer_create(clockid_t clockid, struct sigevent *evp,\r\n\u00a0timer_t *timerid);\r\n\u00a0int timer_settime(timer_t timerid, int flags,\r\n\u00a0const struct itimerspec *new_value,\r\n\u00a0struct itimerspec * old_value);\r\n\u00a0int timer_gettime(timer_t timerid, struct itimerspec *curr_value); \r\n\u00a0int timer_getoverrun(timer_t timerid);\r\n\u00a0int timer_delete(timer_t timerid);<\/pre>\n<div class=\"ibm-syntax-container\">\n<div>\n<div id=\"highlighter_380304\" class=\"syntaxhighlighter  htmlscript\"><\/div>\n<\/div>\n<\/div>\n<p>\u8fd9\u5957\u63a5\u53e3\u662f\u4e3a\u4e86\u8ba9\u64cd\u4f5c\u7cfb\u7edf\u5bf9\u5b9e\u65f6\u6709\u66f4\u597d\u7684\u652f\u6301\uff0c\u5728\u94fe\u63a5\u65f6\u9700\u8981\u6307\u5b9a -lrt \u3002<\/p>\n<p>timer_create(2): \u521b\u5efa\u4e86\u4e00\u4e2a\u5b9a\u65f6\u5668\u3002<\/p>\n<p>timer_settime(2): \u542f\u52a8\u6216\u8005\u505c\u6b62\u4e00\u4e2a\u5b9a\u65f6\u5668\u3002<\/p>\n<p>timer_gettime(2): \u8fd4\u56de\u5230\u4e0b\u4e00\u6b21\u5230\u671f\u7684\u5269\u4f59\u65f6\u95f4\u503c\u548c\u5b9a\u65f6\u5668\u5b9a\u4e49\u7684\u65f6\u95f4\u95f4\u9694\u3002\u51fa\u73b0\u8be5\u63a5\u53e3\u7684\u539f\u56e0\u662f\uff0c\u5982\u679c\u7528\u6237\u5b9a\u4e49\u4e86\u4e00\u4e2a 1ms \u7684\u5b9a\u65f6\u5668\uff0c\u53ef\u80fd\u5f53\u65f6\u7cfb\u7edf\u8d1f\u8377\u5f88\u91cd\uff0c\u5bfc\u81f4\u8be5\u5b9a\u65f6\u5668\u5b9e\u9645\u5c71 10ms \u540e\u624d\u8d85\u65f6\uff0c\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0coverrun=9ms \u3002<\/p>\n<p>timer_getoverrun(2): \u8fd4\u56de\u4e0a\u6b21\u5b9a\u65f6\u5668\u5230\u671f\u65f6\u8d85\u9650\u503c\u3002<\/p>\n<p>timer_delete(2): \u505c\u6b62\u5e76\u5220\u9664\u4e00\u4e2a\u5b9a\u65f6\u5668\u3002<\/p>\n<p>\u4e0a\u9762\u6700\u91cd\u8981\u7684\u63a5\u53e3\u662f timer_create(2)\uff0c\u5176\u4e2d\uff0cclockid \u8868\u660e\u4e86\u8981\u4f7f\u7528\u7684\u65f6\u949f\u7c7b\u578b\uff0c\u5728 POSIX \u4e2d\u8981\u6c42\u5fc5\u987b\u5b9e\u73b0 CLOCK_REALTIME \u7c7b\u578b\u7684\u65f6\u949f\u3002 evp \u53c2\u6570\u6307\u660e\u4e86\u5728\u5b9a\u65f6\u5230\u671f\u540e\uff0c\u8c03\u7528\u8005\u88ab\u901a\u77e5\u7684\u65b9\u5f0f\u3002\u8be5\u7ed3\u6784\u4f53\u5b9a\u4e49\u5982\u4e0b :<\/p>\n<h5 id=\"N100EE\" class=\"ibm-h5\">\u6e05\u5355 9. POSIX timer \u63a5\u53e3\u4e2d\u7684\u4fe1\u53f7\u548c\u4e8b\u4ef6\u5b9a\u4e49<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">union sigval {\r\n\u00a0int sival_int;\r\n\u00a0void *sival_ptr;\r\n\u00a0};\r\n\r\n\u00a0struct sigevent {\r\n\u00a0int sigev_notify; \/* Notification method *\/\r\n\u00a0int sigev_signo; \/* Timer expiration signal *\/\r\n\u00a0union sigval sigev_value; \/* Value accompanying signal or \r\n\u00a0passed to thread function *\/\r\n\u00a0void (*sigev_notify_function) (union sigval);\r\n\u00a0\/* Function used for thread\r\n\u00a0notifications (SIGEV_THREAD) *\/\r\n\u00a0void *sigev_notify_attributes;\r\n\u00a0\/* Attributes for notification thread\r\n\u00a0(SIGEV_THREAD) *\/\r\n\u00a0pid_t sigev_notify_thread_id;\r\n\u00a0\/* ID of thread to signal (SIGEV_THREAD_ID) *\/\r\n\u00a0};<\/pre>\n<div class=\"ibm-syntax-container\">\n<div>\n<div id=\"highlighter_403708\" class=\"syntaxhighlighter  htmlscript\"><\/div>\n<\/div>\n<\/div>\n<p>\u5176\u4e2d\uff0csigev_notify \u6307\u660e\u4e86\u901a\u77e5\u7684\u65b9\u5f0f :<\/p>\n<p>SIGEV_NONE<\/p>\n<p>\u5f53\u5b9a\u65f6\u5668\u5230\u671f\u65f6\uff0c\u4e0d\u53d1\u9001\u5f02\u6b65\u901a\u77e5\uff0c\u4f46\u8be5\u5b9a\u65f6\u5668\u7684\u8fd0\u884c\u8fdb\u5ea6\u53ef\u4ee5\u4f7f\u7528 timer_gettime(2) \u76d1\u6d4b\u3002<\/p>\n<p>SIGEV_SIGNAL<\/p>\n<p>\u5f53\u5b9a\u65f6\u5668\u5230\u671f\u65f6\uff0c\u53d1\u9001 sigev_signo \u6307\u5b9a\u7684\u4fe1\u53f7\u3002<\/p>\n<p>SIGEV_THREAD<\/p>\n<p>\u5f53\u5b9a\u65f6\u5668\u5230\u671f\u65f6\uff0c\u4ee5 sigev_notify_function \u5f00\u59cb\u4e00\u4e2a\u65b0\u7684\u7ebf\u7a0b\u3002\u8be5\u51fd\u6570\u4f7f\u7528 sigev_value \u4f5c\u4e3a\u5176\u53c2\u6570\uff0c\u5f53 sigev_notify_attributes \u975e\u7a7a\uff0c\u5219\u5236\u5b9a\u8be5\u7ebf\u7a0b\u7684\u5c5e\u6027\u3002\u6ce8\u610f\uff0c\u7531\u4e8e Linux \u4e0a\u7ebf\u7a0b\u7684\u7279\u6b8a\u6027\uff0c\u8fd9\u4e2a\u529f\u80fd\u5b9e\u9645\u4e0a\u662f\u7531 glibc \u548c\u5185\u6838\u4e00\u8d77\u5b9e\u73b0\u7684\u3002<\/p>\n<p>SIGEV_THREAD_ID (Linux-specific)<\/p>\n<p>\u4ec5\u63a8\u8350\u5728\u5b9e\u73b0\u7ebf\u7a0b\u5e93\u65f6\u5019\u4f7f\u7528\u3002<\/p>\n<p>\u5982\u679c evp \u4e3a\u7a7a\u7684\u8bdd\uff0c\u5219\u8be5\u51fd\u6570\u7684\u884c\u4e3a\u7b49\u6548\u4e8e\uff1asigev_notify = SIGEV_SIGNAL\uff0csigev_signo = SIGVTALRM\uff0csigev_value.sival_int = timer ID \u3002<\/p>\n<p>\u7531\u4e8e POSIX timer \uff3b 2 \uff3d\u63a5\u53e3\u652f\u6301\u5728\u4e00\u4e2a\u8fdb\u7a0b\u4e2d\u540c\u65f6\u62e5\u6709\u591a\u4e2a\u5b9a\u65f6\u5668\u5b9e\u4f8b\uff0c\u6240\u4ee5\u5728\u4e0a\u9762\u7684\u57fa\u4e8e setitimer() \u548c\u94fe\u8868\u7684 PerTickBookkeeping \u52a8\u4f5c\u5c31\u4ea4\u7531 Linux \u5185\u6838\u6765\u7ef4\u62a4\uff0c\u8fd9\u5927\u5927\u51cf\u8f7b\u4e86\u5b9e\u73b0\u5b9a\u65f6\u5668\u7684\u8d1f\u62c5\u3002\u7531\u4e8e POSIX timer \uff3b 2 \uff3d\u63a5\u53e3\u5728\u5b9a\u65f6\u5668\u5230\u671f\u65f6\uff0c\u6709\u66f4\u591a\u7684\u63a7\u5236\u80fd\u529b\uff0c\u56e0\u6b64\uff0c\u53ef\u4ee5\u4f7f\u7528\u5b9e\u65f6\u4fe1\u53f7\u907f\u514d\u4fe1\u53f7\u7684\u4e22\u5931\u95ee\u9898\uff0c\u5e76\u5c06 sigev_value.sival_int \u503c\u6307\u5b9a\u4e3a timer ID\uff0c\u8fd9\u6837\uff0c\u5c31\u53ef\u4ee5\u5c06\u591a\u4e2a\u5b9a\u65f6\u5668\u4e00\u8d77\u7ba1\u7406\u4e86\u3002\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0cPOSIX timer \uff3b 2 \uff3d\u63a5\u53e3\u53ea\u5728\u8fdb\u7a0b\u73af\u5883\u4e0b\u624d\u6709\u610f\u4e49 (fork(2) \u548c exec(2) \u4e5f\u9700\u8981\u7279\u6b8a\u5bf9\u5f85 )\uff0c\u5e76\u4e0d\u9002\u5408\u591a\u7ebf\u7a0b\u73af\u5883\u3002\u4e0e\u6b64\u76f8\u7c7b\u4f3c\u7684\uff0cLinux \u63d0\u4f9b\u4e86\u57fa\u4e8e\u6587\u4ef6\u63cf\u8ff0\u7b26\u7684\u76f8\u5173\u5b9a\u65f6\u5668\u63a5\u53e3\uff1a<\/p>\n<h5 id=\"N1010C\" class=\"ibm-h5\">\u6e05\u5355 10. Linux \u63d0\u4f9b\u7684\u57fa\u4e8e\u6587\u4ef6\u63cf\u8ff0\u7b26\u7684\u5b9a\u65f6\u5668\u63a5\u53e3<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">#include &lt;sys\/timerfd.h&gt;\r\n\r\n\u00a0int timerfd_create(int clockid, int flags);\r\n\u00a0int timerfd_settime(int fd, int flags,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const struct itimerspec *new_value, \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct itimerspec *old_value);\r\n\u00a0int timerfd_gettime(int fd, struct itimerspec *curr_value);<\/pre>\n<p>&nbsp;<\/p>\n<p>\u8fd9\u6837\uff0c\u7531\u4e8e\u57fa\u4e8e\u6587\u4ef6\u63cf\u8ff0\u7b26\uff0c\u4f7f\u5f97\u8be5\u63a5\u53e3\u53ef\u4ee5\u652f\u6301 select(2)\uff0cpoll(2) \u7b49\u5f02\u6b65\u63a5\u53e3\uff0c\u4f7f\u5f97\u5b9a\u65f6\u5668\u7684\u5b9e\u73b0\u548c\u4f7f\u7528\u66f4\u52a0\u7684\u65b9\u4fbf\uff0c\u66f4\u91cd\u8981\u7684\u662f\uff0c\u652f\u6301 fork(2)\uff0cexec(2) \u8fd9\u6837\u591a\u8fdb\u7a0b\u7684\u8bed\u4e49\uff0c\u56e0\u6b64\uff0c\u53ef\u4ee5\u7528\u5728\u591a\u7ebf\u7a0b\u73af\u5883\u4e4b\u4e2d\uff0c\u5b83\u4eec\u7684\u4f7f\u7528\u6bd4 POSIX timer \uff3b 2 \uff3d\u66f4\u52a0\u7684\u7075\u6d3b\uff0c\u5176\u6839\u672c\u539f\u56e0\u5728\u4e8e\u5b9a\u65f6\u5668\u7684\u7ba1\u7406\u7edf\u4e00\u5230\u4e86 unix\/linux \u57fa\u672c\u54f2\u5b66\u4e4b\u4e00 &#8212;- \u201c\u4e00\u5207\u7686\u6587\u4ef6\u201d\u4e4b\u4e0b\u3002<\/p>\n<h2 id=\"4\u6700\u5c0f\u5806\u5b9e\u73b0\u7684\u5b9a\u65f6\u5668outline\" class=\"ibm-h2\">\u6700\u5c0f\u5806\u5b9e\u73b0\u7684\u5b9a\u65f6\u5668<\/h2>\n<p>\u6700\u5c0f\u5806\u6307\u7684\u662f\u6ee1\u8db3\u9664\u4e86\u6839\u8282\u70b9\u4ee5\u5916\u7684\u6bcf\u4e2a\u8282\u70b9\u90fd\u4e0d\u5c0f\u4e8e\u5176\u7236\u8282\u70b9\u7684\u5806\u3002\u8fd9\u6837\uff0c\u5806\u4e2d\u7684\u6700\u5c0f\u503c\u5c31\u5b58\u653e\u5728\u6839\u8282\u70b9\u4e2d\uff0c\u5e76\u4e14\u5728\u4ee5\u67d0\u4e2a\u7ed3\u70b9\u4e3a\u6839\u7684\u5b50\u6811\u4e2d\uff0c\u5404\u8282\u70b9\u7684\u503c\u90fd\u4e0d\u5c0f\u4e8e\u8be5\u5b50\u6811\u6839\u8282\u70b9\u7684\u503c\u3002\u4e00\u4e2a\u6700\u5c0f\u5806\u7684\u4f8b\u5b50\u5982\u4e0b\u56fe 2\uff1a<\/p>\n<h5 id=\"N1011C\" class=\"ibm-h5\">\u56fe 2. \u6700\u5c0f\u5806<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"ibm-downsize\" src=\"https:\/\/www.ibm.com\/developerworks\/cn\/linux\/l-cn-timers\/image002.jpg\" alt=\"\u6700\u5c0f\u5806\" width=\"442\" height=\"286\" \/><\/p>\n<p>\u4e00\u4e2a\u6700\u5c0f\u5806\uff0c\u4e00\u822c\u652f\u6301\u4ee5\u4e0b\u51e0\u79cd\u64cd\u4f5c\uff1a<\/p>\n<p>Insert(TimerHeap, Timer): \u5728\u5806\u4e2d\u63d2\u5165\u4e00\u4e2a\u503c\uff0c\u5e76\u4fdd\u6301\u6700\u5c0f\u5806\u6027\u8d28\uff0c\u5177\u4f53\u5bf9\u5e94\u4e8e\u5b9a\u65f6\u5668\u7684\u5b9e\u73b0\uff0c\u5219\u662f\u628a\u5b9a\u65f6\u5668\u63d2\u5165\u5230\u5b9a\u65f6\u5668\u5806\u4e2d\u3002\u6839\u636e\u6700\u5c0f\u5806\u7684\u63d2\u5165\u7b97\u6cd5\u5206\u6790\uff0c\u53ef\u4ee5\u77e5\u9053\u8be5\u64cd\u4f5c\u7684\u65f6\u95f4\u590d\u6742\u5ea6\u4e3a O(lgn) \u3002<\/p>\n<p>Minimum(TimerHeap): \u83b7\u53d6\u6700\u5c0f\u5806\u7684\u4e2d\u6700\u5c0f\u503c\uff1b\u5728\u5b9a\u65f6\u5668\u7cfb\u7edf\u4e2d\uff0c\u5219\u662f\u8fd4\u56de\u5b9a\u65f6\u5668\u5806\u4e2d\u6700\u5148\u53ef\u80fd\u7ec8\u6b62\u7684\u5b9a\u65f6\u5668\u3002\u7531\u4e8e\u662f\u6700\u5c0f\u5806\uff0c\u53ea\u9700\u8fd4\u56de\u5806\u7684 root \u5373\u53ef\u3002\u6b64\u65f6\u7684\u7b97\u6cd5\u590d\u6742\u5ea6\u4e3a O(1) \u3002<\/p>\n<p>ExtractMin(TimerHeap): \u5728\u5b9a\u65f6\u5668\u5230\u671f\u540e\uff0c\u6267\u884c\u76f8\u5173\u7684\u52a8\u4f5c\uff0c\u5b83\u7684\u7b97\u6cd5\u590d\u6742\u5ea6\u4e3a O(1) \u3002<\/p>\n<p>\u6700\u5c0f\u5806\u672c\u8d28\u4e0a\u662f\u4e00\u79cd\u6700\u5c0f\u4f18\u5148\u7ea7\u961f\u5217 (min-priority queue) \u3002\u5b9a\u65f6\u53ef\u4ee5\u4f5c\u4e3a\u6700\u5c0f\u4f18\u5148\u7ea7\u961f\u5217\u7684\u4e00\u4e2a\u5e94\u7528\uff0c\u8be5\u4f18\u5148\u7ea7\u961f\u5217\u628a\u5b9a\u65f6\u5668\u7684\u65f6\u95f4\u95f4\u9694\u503c\u8f6c\u5316\u4e3a\u4e00\u4e2a\u7edd\u5bf9\u65f6\u95f4\u6765\u5904\u7406\uff0cExtractMin \u64cd\u5219\u662f\u5728\u6240\u6709\u7b49\u5f85\u7684\u5b9a\u65f6\u5668\u4e2d\uff0c\u627e\u51fa\u6700\u5148\u8d85\u65f6\u7684\u5b9a\u65f6\u5668\u3002\u5728\u4efb\u4f55\u65f6\u5019\uff0c\u4e00\u4e2a\u65b0\u7684\u5b9a\u65f6\u5668\u5b9e\u4f8b\u90fd\u53ef\u901a\u8fc7 Insert \u64cd\u4f5c\u52a0\u5165\u5230\u5b9a\u65f6\u5668\u961f\u5217\u4e2d\u53bb\u3002<\/p>\n<p>\u5728 pjsip \u9879\u76ee\u7684\u57fa\u7840\u5e93 pjlib \u4e2d\uff0c\u6709\u57fa\u4e8e\u6700\u5c0f\u5806\u5b9e\u73b0\u7684\u5b9a\u65f6\u5668\uff0c\u5b83\u4e3b\u8981\u63d0\u4f9b\u4e86\u4ee5\u4e0b\u7684\u51e0\u4e2a\u63a5\u53e3\uff1a<\/p>\n<h5 id=\"N10133\" class=\"ibm-h5\">\u6e05\u5355 10. pjlib \u63d0\u4f9b\u7684\u57fa\u4e8e\u6700\u5c0f\u5806\u7684\u5b9a\u65f6\u5668\u63a5\u53e3<\/h5>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">\/**\r\n\u00a0* Create a timer heap.\r\n\u00a0*\/\r\n\u00a0PJ_DECL(pj_status_t) pj_timer_heap_create( pj_pool_t *pool,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pj_size_t count,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pj_timer_heap_t **ht);\r\n\r\n\u00a0\/**\r\n\u00a0* Destroy the timer heap.\r\n\u00a0*\/\r\n\u00a0PJ_DECL(void) pj_timer_heap_destroy( pj_timer_heap_t *ht );\r\n\r\n\u00a0\/**\r\n\u00a0* Initialize a timer entry. Application should call this function at least\r\n\u00a0* once before scheduling the entry to the timer heap, to properly initialize\r\n\u00a0* the timer entry.\r\n\u00a0*\/\r\n\u00a0PJ_DECL(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0int id,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0void *user_data,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pj_timer_heap_callback *cb ); \r\n\r\n\u00a0\/**\r\n\u00a0* Schedule a timer entry which will expire AFTER the specified delay.\r\n\u00a0*\/\r\n\u00a0PJ_DECL(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pj_timer_entry *entry,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const pj_time_val *delay);\r\n\r\n\u00a0\/**\r\n\u00a0* Cancel a previously registered timer.\r\n\u00a0*\/\r\n\u00a0PJ_DECL(int) pj_timer_heap_cancel( pj_timer_heap_t *ht,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pj_timer_entry *entry);\r\n\r\n\u00a0\/**\r\n\u00a0* Poll the timer heap, check for expired timers and call the callback for\r\n\u00a0* each of the expired timers.\r\n\u00a0*\/\r\n\u00a0PJ_DECL(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pj_time_val *next_delay);<\/pre>\n<div class=\"ibm-syntax-container\">\n<div>\n<div id=\"highlighter_156045\" class=\"syntaxhighlighter  htmlscript\"><\/div>\n<\/div>\n<\/div>\n<p>pjlib \u4e2d\u7684\u5b9a\u65f6\u5668\u5728\u5185\u90e8\u4f7f\u7528\u6570\u7ec4\u7684\u65b9\u5f0f\u5b9e\u73b0\u5806\uff0c\u8fd9\u6837\u5bf9\u4e8e\u5185\u5b58\u7a7a\u95f4\u7684\u4f7f\u7528\u5c06\u66f4\u52a0\u7684\u7d27\u51d1\uff1b\u5b83\u7684\u5b9e\u73b0\u8fd8\u53ef\u5728\u5b9a\u65f6\u5668\u7684\u6570\u91cf\u8d85\u8fc7\u9884\u5148\u8bbe\u5b9a\u7684\u6700\u5927\u6570\u91cf\u65f6\u4f1a\u81ea\u5df1\u589e\u52a0\u6700\u5927\u5b9a\u65f6\u5668\u6570\u91cf\u3002\u6587\u4ef6 pjlib\/src\/pjlib-test\/timer.c \u662f\u5b83\u7684\u4e00\u4e2a\u5355\u5143\u6d4b\u8bd5\u3002\u4e0e\u57fa\u4e8e\u94fe\u8868\u65b9\u5f0f\u7684\u5b9e\u73b0\u76f8\u6bd4\u8f83\uff0c\u660e\u663e\u5b83\u7684\u65f6\u95f4\u590d\u6742\u5ea6\u8981\u4f4e\u4e00\u4e9b\uff0c\u8fd9\u6837\u53ef\u4ee5\u652f\u6301\u66f4\u591a\u7684\u5b9a\u65f6\u5668\u5b9e\u4f8b\u3002<\/p>\n<h2 id=\"5\u57fa\u4e8e\u65f6\u95f4\u8f6eTiming-Wheel\u65b9\u5f0f\u5b9e\u73b0\u7684\u5b9a\u65f6\u5668outline\" class=\"ibm-h2\">\u57fa\u4e8e\u65f6\u95f4\u8f6e (Timing-Wheel) \u65b9\u5f0f\u5b9e\u73b0\u7684\u5b9a\u65f6\u5668<\/h2>\n<p>\u65f6\u95f4\u8f6e (Timing-Wheel) \u7b97\u6cd5\u7c7b\u4f3c\u4e8e\u4e00\u4ee5\u6052\u5b9a\u901f\u5ea6\u65cb\u8f6c\u7684\u5de6\u8f6e\u624b\u67aa\uff0c\u67aa\u7684\u649e\u9488\u5219\u649e\u51fb\u67aa\u819b\uff0c\u5982\u679c\u67aa\u819b\u4e2d\u6709\u5b50\u5f39\uff0c\u5219\u4f1a\u88ab\u51fb\u53d1\uff1b\u4e0e\u4e4b\u76f8\u5bf9\u5e94\u7684\u662f\uff1a\u5bf9\u4e8e PerTickBookkeeping\uff0c\u5176\u6700\u672c\u8d28\u7684\u5de5\u4f5c\u5728\u4e8e\u4ee5 Tick \u4e3a\u5355\u4f4d\u589e\u52a0\u65f6\u949f\uff0c\u5982\u679c\u53d1\u73b0\u6709\u4efb\u4f55\u5b9a\u65f6\u5668\u5230\u671f\uff0c\u5219\u8c03\u7528\u76f8\u5e94\u7684 ExpiryProcessing \u3002\u8bbe\u5b9a\u4e00\u4e2a\u5faa\u73af\u4e3a N \u4e2a Tick \u5355\u5143\uff0c\u5f53\u524d\u65f6\u95f4\u662f\u5728 S \u4e2a\u5faa\u73af\u4e4b\u540e\u6307\u5411\u5143\u7d20 i (i&gt;=0 and i&lt;= N &#8211; 1)\uff0c\u5219\u5f53\u524d\u65f6\u95f4 (Current Time)Tc \u53ef\u4ee5\u8868\u793a\u4e3a\uff1aTc = S*N + i \uff1b\u5982\u679c\u6b64\u65f6\u63d2\u5165\u4e00\u4e2a\u65f6\u95f4\u95f4\u9694 (Time Interval) \u4e3a Ti \u7684\u5b9a\u65f6\u5668\uff0c\u8bbe\u5b9a\u5b83\u5c06\u4f1a\u653e\u5165\u5143\u7d20 n(Next) \u4e2d\uff0c\u5219 n = \uff08Tc + Ti\uff09mod N = (S*N + i + Ti) mod N = (i + Ti) mod N \u3002\u5982\u679c\u6211\u4eec\u7684 N \u8db3\u591f\u7684\u5927\uff0c\u663e\u7136 StartTimer\uff0cStopTimer\uff0cPerTickBookkeeping \u65f6\uff0c\u7b97\u6cd5\u590d\u6742\u5ea6\u5206\u522b\u4e3a O(1)\uff0cO(1)\uff0cO(1) \u3002\u5728 [5] \u4e2d\uff0c\u7ed9\u51fa\u4e86\u4e00\u4e2a\u7b80\u5355\u5b9a\u65f6\u5668\u8f6e\u5b9e\u73b0\u7684\u5b9a\u65f6\u3002\u4e0b\u56fe 3 \u662f\u4e00\u4e2a\u7b80\u5355\u7684\u65f6\u95f4\u8f6e\u5b9a\u65f6\u5668\uff1a<\/p>\n<h5 id=\"N10143\" class=\"ibm-h5\">\u56fe 3. \u7b80\u5355\u65f6\u95f4\u8f6e<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"ibm-downsize\" src=\"https:\/\/www.ibm.com\/developerworks\/cn\/linux\/l-cn-timers\/image003.jpg\" alt=\"\u7b80\u5355\u65f6\u95f4\u8f6e\" width=\"412\" height=\"227\" \/><\/p>\n<p>\u5982\u679c\u9700\u8981\u652f\u6301\u7684\u5b9a\u65f6\u5668\u8303\u56f4\u975e\u5e38\u7684\u5927\uff0c\u4e0a\u9762\u7684\u5b9e\u73b0\u65b9\u5f0f\u5219\u4e0d\u80fd\u6ee1\u8db3\u8fd9\u6837\u7684\u9700\u6c42\u3002\u56e0\u4e3a\u8fd9\u6837\u5c06\u6d88\u8017\u975e\u5e38\u53ef\u89c2\u7684\u5185\u5b58\uff0c\u5047\u8bbe\u9700\u8981\u8868\u793a\u7684\u5b9a\u65f6\u5668\u8303\u56f4\u4e3a\uff1a0 \u2013 2^3-1ticks\uff0c\u5219\u7b80\u5355\u65f6\u95f4\u8f6e\u9700\u8981 2^32 \u4e2a\u5143\u7d20\u7a7a\u95f4\uff0c\u8fd9\u5bf9\u4e8e\u5185\u5b58\u7a7a\u95f4\u7684\u4f7f\u7528\u5c06\u975e\u5e38\u7684\u5e9e\u5927\u3002\u4e5f\u8bb8\u53ef\u4ee5\u964d\u4f4e\u5b9a\u65f6\u5668\u7684\u7cbe\u5ea6\uff0c\u4f7f\u5f97\u6bcf\u4e2a Tick \u8868\u793a\u7684\u65f6\u95f4\u66f4\u957f\u4e00\u4e9b\uff0c\u4f46\u8fd9\u6837\u7684\u4ee3\u4ef7\u662f\u5b9a\u65f6\u5668\u7684\u7cbe\u5ea6\u5c06\u5927\u6253\u6298\u6263\u3002\u73b0\u5728\u7684\u95ee\u9898\u662f\uff0c\u5ea6\u91cf\u5b9a\u65f6\u5668\u7684\u7c92\u5ea6\uff0c\u53ea\u80fd\u4f7f\u7528\u552f\u4e00\u7c92\u5ea6\u5417\uff1f\u60f3\u60f3\u65e5\u5e38\u751f\u6d3b\u4e2d\u5e38\u9047\u5230\u7684\u6c34\u8868\uff0c\u5982\u4e0b\u56fe 4\uff1a<\/p>\n<h5 id=\"N1014F\" class=\"ibm-h5\">\u56fe 4. \u6c34\u8868<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"ibm-downsize\" src=\"https:\/\/www.ibm.com\/developerworks\/cn\/linux\/l-cn-timers\/image004.jpg\" alt=\"\u6c34\u8868\" width=\"576\" height=\"480\" \/><\/p>\n<p>\u5728\u4e0a\u9762\u7684\u6c34\u8868\u4e2d\uff0c\u4e3a\u4e86\u8868\u793a\u5ea6\u91cf\u8303\u56f4\uff0c\u5206\u6210\u4e86\u4e0d\u540c\u7684\u5355\u4f4d\uff0c\u6bd4\u5982 1000\uff0c100\uff0c10 \u7b49\u7b49\uff0c\u76f8\u4f3c\u7684\uff0c\u8868\u793a\u4e00\u4e2a 32bits \u7684\u8303\u56f4\uff0c\u4e5f\u4e0d\u9700\u8981 2^32 \u4e2a\u5143\u7d20\u7684\u6570\u7ec4\u3002\u5b9e\u9645\u4e0a\uff0cLinux \u7684\u5185\u6838\u628a\u5b9a\u65f6\u5668\u5206\u4e3a 5 \u7ec4\uff0c\u6bcf\u7ec4\u7684\u7c92\u5ea6\u5206\u522b\u8868\u793a\u4e3a\uff1a1 jiffies\uff0c256 jiffies\uff0c256*64 jiffies\uff0c256*64*64 jiffies\uff0c256*64*64*64 jiffies\uff0c\u6bcf\u7ec4\u4e2d\u6876\u7684\u6570\u91cf\u5206\u522b\u4e3a\uff1a256\uff0c64\uff0c64\uff0c64\uff0c64\uff0c\u8fd9\u6837\uff0c\u5728 256+64+64+64+64 = 512 \u4e2a\u6876\u4e2d\uff0c\u8868\u793a\u7684\u8303\u56f4\u4e3a 2^32 \u3002\u6709\u4e86\u8fd9\u6837\u7684\u5b9e\u73b0\uff0c\u9a71\u52a8\u5185\u6838\u5b9a\u65f6\u5668\u7684\u673a\u5236\u4e5f\u53ef\u4ee5\u901a\u8fc7\u6c34\u8868\u7684\u4f8b\u5b50\u6765\u7406\u89e3\u4e86\uff0c\u5c31\u50cf\u6c34\u8868\uff0c\u6bcf\u4e2a\u7c92\u5ea6\u4e0a\u90fd\u6709\u4e00\u4e2a\u6307\u9488\u6307\u5411\u5f53\u524d\u65f6\u95f4\uff0c\u65f6\u95f4\u4ee5\u56fa\u5b9a tick \u9012\u589e\uff0c\u800c\u5f53\u524d\u65f6\u95f4\u6307\u9488\u5219\u4e5f\u4f9d\u6b21\u9012\u589e\uff0c\u5982\u679c\u53d1\u73b0\u5f53\u524d\u6307\u9488\u7684\u4f4d\u7f6e\u53ef\u4ee5\u786e\u5b9a\u4e3a\u4e00\u4e2a\u6ce8\u518c\u7684\u5b9a\u65f6\u5668\uff0c\u5c31\u89e6\u53d1\u5176\u6ce8\u518c\u7684\u56de\u8c03\u51fd\u6570\u3002 Linux \u5185\u6838\u5b9a\u65f6\u5668\u672c\u8d28\u4e0a\u662f Single-Shot Timer\uff0c\u5982\u679c\u60f3\u6210\u4e3a Repeating Timer\uff0c\u53ef\u4ee5\u5728\u6ce8\u518c\u7684\u56de\u8c03\u51fd\u6570\u4e2d\u518d\u6b21\u7684\u6ce8\u518c\u81ea\u5df1\u3002\u5185\u6838\u5b9a\u65f6\u5668\u5982\u4e0b\u56fe 5\uff1a<\/p>\n<h5 id=\"N1015B\" class=\"ibm-h5\">\u56fe 5. Linux \u65f6\u95f4\u8f6e<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"ibm-downsize\" src=\"https:\/\/www.ibm.com\/developerworks\/cn\/linux\/l-cn-timers\/image005.jpg\" alt=\"Linux\u65f6\u95f4\u8f6e\" width=\"576\" height=\"360\" \/><a id=\"_\u4ee3\u7801\u6e05\u5355\u4e0e\u9884\u683c\u5f0f\u5316\u6587\u672c\"><\/a><\/p>\n<h2 id=\"6\u7ed3\u8bbaoutline\" class=\"ibm-h2\">\u7ed3\u8bba<\/h2>\n<p>\u7531\u4e0a\u9762\u7684\u5206\u6790\uff0c\u53ef\u4ee5\u770b\u5230\u5404\u79cd\u5b9a\u65f6\u5668\u5b9e\u73b0\u7b97\u6cd5\u7684\u590d\u6742\u5ea6\uff1a<\/p>\n<h5 id=\"\u8868\u683c1|table\" class=\"ibm-h5\">\u8868 1. \u5b9a\u65f6\u5668\u5b9e\u73b0\u7b97\u6cd5\u590d\u6742\u5ea6<\/h5>\n<div id=\"DataTables_Table_0_wrapper\" class=\"dataTables_wrapper no-footer\">\n<table id=\"DataTables_Table_0\" class=\"ibm-data-table display dataTable no-footer dtr-inline ibm-widget-processed\" role=\"grid\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" data-widget=\"datatable\">\n<thead>\n<tr role=\"row\">\n<th class=\"ibm-background-neutral-white-30 sorting_disabled\" colspan=\"1\" rowspan=\"1\">\u5b9e\u73b0\u65b9\u5f0f<\/th>\n<th class=\"ibm-background-neutral-white-30 sorting_disabled\" colspan=\"1\" rowspan=\"1\">StartTimer<\/th>\n<th class=\"ibm-background-neutral-white-30 sorting_disabled\" colspan=\"1\" rowspan=\"1\">StopTimer<\/th>\n<th class=\"ibm-background-neutral-white-30 sorting_disabled\" colspan=\"1\" rowspan=\"1\">PerTickBookkeeping<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"odd\" role=\"row\">\n<td tabindex=\"0\">\u57fa\u4e8e\u94fe\u8868<\/td>\n<td>O(1)<\/td>\n<td>O(n)<\/td>\n<td>O(n)<\/td>\n<\/tr>\n<tr class=\"even\" role=\"row\">\n<td tabindex=\"0\">\u57fa\u4e8e\u6392\u5e8f\u94fe\u8868<\/td>\n<td>O(n)<\/td>\n<td>O(1)<\/td>\n<td>O(1)<\/td>\n<\/tr>\n<tr class=\"odd\" role=\"row\">\n<td tabindex=\"0\">\u57fa\u4e8e\u6700\u5c0f\u5806<\/td>\n<td>O(lgn)<\/td>\n<td>O(1)<\/td>\n<td>O(1)<\/td>\n<\/tr>\n<tr class=\"even\" role=\"row\">\n<td tabindex=\"0\">\u57fa\u4e8e\u65f6\u95f4\u8f6e<\/td>\n<td>O(1)<\/td>\n<td>O(1)<\/td>\n<td>O(1)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>\u5982\u679c\u9700\u8981\u80fd\u5728\u7ebf\u7a0b\u73af\u5883\u4e2d\u4f7f\u7528\u7684\u5b9a\u65f6\u5668\uff0c\u5bf9\u4e8e\u57fa\u4e8e\u94fe\u8868\u7684\u5b9a\u65f6\u5668\uff0c\u53ef\u80fd\u9700\u8981\u5f88\u5c0f\u5fc3\u7684\u5904\u7406\u4fe1\u53f7\u7684\u95ee\u9898\uff1b\u800c POSIX timer \uff3b 2 \uff3d\u63a5\u53e3\u7684\u5b9a\u65f6\u5668\uff0c\u53ea\u5177\u6709\u8fdb\u7a0b\u7684\u8bed\u4e49\uff0c\u5982\u679c\u60f3\u5728\u591a\u7ebf\u7a0b\u73af\u5883\u4e0b\u4e5f n \u80fd\u4f7f\u7528\uff0c\u53ef\u4ee5\u4f7f\u7528 Linux \u63d0\u4f9b\u7684 timerfd_create(2) \u63a5\u53e3\u3002\u5982\u679c\u9700\u8981\u652f\u6301\u7684\u5b9a\u65f6\u5668\u6570\u91cf\u975e\u5e38\u7684\u5927\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528\u57fa\u4e8e\u6700\u5c0f\u5806\u548c\u65f6\u95f4\u8f6e\u7684\u65b9\u5f0f\u6765\u5b9e\u73b0\u3002<\/p>\n<div class=\"ibm-alternate-rule\"><\/div>\n<h4 id=\"artdownload\" class=\"ibm-h4\">\u4e0b\u8f7d\u8d44\u6e90<\/h4>\n<ul class=\"ibm-link-list\">\n<li><a class=\"ibm-download-link\" href=\"http:\/\/www.ibm.com\/developerworks\/apps\/download\/index.jsp?contentid=442490&amp;filename=test-signal.c&amp;method=http&amp;locale=zh_CN\">\u6837\u4f8b\u4ee3\u7801<\/a>\u00a0(test-signal.c | 7KB)<\/li>\n<\/ul>\n<div class=\"ibm-alternate-rule\"><\/div>\n<h4 id=\"artrelatedtopics\" class=\"ibm-h4\">\u76f8\u5173\u4e3b\u9898<\/h4>\n<ul>\n<li>George Varghese ,\u00a0Tony Lauck. Hashed and Hierarchical Timing Wheels: Efficient Data Structures for Implementing a Timer Facility \uff0c\u8fd9\u7bc7\u8bba\u6587\u5206\u6790\u4e86\u5404\u79cd\u5b9a\u65f6\u5668\u5b9e\u73b0\u65b9\u6cd5\uff0c\u5e76\u63d0\u51fa\u4e86\u65f6\u95f4\u8f6e\u7684\u6982\u5ff5\u3002\u5982\u679c\u4f60\u60f3\u5f88\u597d\u7684\u5b9e\u73b0\u4e00\u4e2a\u5b9a\u65f6\u5668\uff0c\u8fd9\u7bc7\u8bba\u6587\u4f60\u9700\u8981\u53cd\u590d\u9605\u8bfb\u3002<\/li>\n<li><a href=\"http:\/\/www.opengroup.org\/onlinepubs\/009695399\/functions\/timer_create.html\">Open Group \u5bf9 POSIX timer \u7684\u63cf\u8ff0<\/a>\u00a0\uff0c\u5982\u679c\u4f60\u5bf9 UNIX \u7684\u6807\u51c6\u6709\u5174\u8da3\uff0c\u63a8\u8350\u4f60\u5728\u8be5\u7f51\u7ad9\u4e0b\u4e00\u4efd\u6700\u65b0\u7684 Specifications\uff0c\u5e76\u4e14\uff0c\u8fd9\u4efd Specifications \u7684\u63cf\u8ff0\u76f8\u5f53\u5bb9\u6613\u8bfb\uff0clinux \u5e94\u7528\u5c42\u7684\u7f16\u7a0b\uff0c\u5b83\u662f\u6211\u9664\u4e86 Steven \u7684\u4e66\u4e4b\u5916\u7684\u7b2c\u4e00\u9009\u62e9\u3002<\/li>\n<li><a href=\"http:\/\/www.pjsip.org\/\">http:\/\/www.pjsip.org\/<\/a>\u00a0\u662f\u4e00\u4e2a Open Source \u7684 VoIP \u9879\u76ee\uff0c\u5982\u679c\u4f60\u4e0d\u5173\u5fc3 VoIP\uff0c\u8be5\u9879\u76ee\u4e2d\u63d0\u4f9b\u7684 pjlib \u5e93\u4e5f\u503c\u5f97\u5173\u6ce8\uff0c\u5b83\u662f\u4e00\u4e2a\u5728\u5d4c\u5165\u5f0f\u73af\u5883\u4e0b\u7684\u901a\u7528\u57fa\u7840\u5e93\u5b9e\u73b0\u7684\u5178\u8303\u3002<\/li>\n<li><a href=\"http:\/\/www.monkey.org\/~provos\/libevent\/\">http:\/\/www.monkey.org\/~provos\/libevent\/<\/a>\u00a0\u6700\u51fa\u540d\u7684\u4e8b\u4ef6\u901a\u77e5\u5e93\u4e4b\u4e00\uff0c\u5b83\u7684\u5185\u90e8\u4f7f\u7528\u57fa\u4e8e\u6700\u5c0f\u5806\u5b9e\u73b0\u7684\u4f18\u5148\u7ea7\u961f\u5217\u5904\u7406\u5305\u62ec\u65f6\u95f4\uff0c\u4fe1\u53f7\u7b49\u5404\u79cd\u4e8b\u4ef6\u3002<\/li>\n<li>Bo Berry \u5728\u6587\u7ae0\u201c<a href=\"http:\/\/www.ddj.com\/embedded\/217800350\">An embedded Single Timer Wheel<\/a>\u201d \u4e2d\u63cf\u8ff0\u4e86\u4e00\u4e2a\u7b80\u5355\u65f6\u95f4\u8f6e\u7b97\u6cd5\u5b9e\u73b0\u7684\u5b9a\u65f6\u5668\u3002<\/li>\n<li><a href=\"http:\/\/www.kernel.org\/pub\/linux\/kernel\/\">Linux 2.6.31-rc6 \u7684\u6e90\u4ee3\u7801<\/a>\u3002<\/li>\n<li><a href=\"http:\/\/lwn.net\/Articles\/156329\/\">http:\/\/lwn.net\/Articles\/156329\/<\/a>Ingo Molnar \u5bf9 linux \u4e2d\u7684\u65f6\u95f4\u8f6e\u7684\u5b9e\u73b0\u505a\u4e86\u6700\u597d\u7684\u89e3\u91ca\u3002<\/li>\n<li><a>Thomas H. Cormen,Charles E. Leiserson,Ronald L. Rivest,Clifford Stein \u8457\uff0e\u7b97\u6cd5\u5bfc\u8bba ( \u7b2c\u4e8c\u7248 ) \uff0e\u5317\u4eac\uff1a\u673a\u68b0\u5de5\u4e1a\u51fa\u7248\u793e\uff0c2006\uff1a73-82 \u3002<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\u6982\u8bba \u5b9a\u65f6\u5668\u5c5e\u4e8e\u57fa\u672c\u7684\u57fa\u7840\u7ec4\u4ef6\uff0c\u4e0d\u7ba1\u662f\u7528<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[],"tags":[119],"class_list":["post-2698","post","type-post","status-publish","format-standard","hentry","tag-03-"],"_links":{"self":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/2698","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/comments?post=2698"}],"version-history":[{"count":0,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/2698\/revisions"}],"wp:attachment":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/media?parent=2698"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/categories?post=2698"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/tags?post=2698"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}