{"id":225,"date":"2025-10-18T18:30:31","date_gmt":"2025-10-18T10:30:31","guid":{"rendered":"http:\/\/47.99.178.170\/?p=225"},"modified":"2025-10-23T22:02:13","modified_gmt":"2025-10-23T14:02:13","slug":"%e3%80%90%e6%ba%90%e7%a0%81%e8%a7%a3%e6%9e%90%e3%80%91uloop%e6%ba%90%e7%a0%81%e8%a7%a3%e6%9e%90","status":"publish","type":"post","link":"https:\/\/www.garfield-blog.top\/?p=225","title":{"rendered":"\u3010\u6e90\u7801\u89e3\u6790\u3011uloop\u6e90\u7801\u89e3\u6790"},"content":{"rendered":"\n<p><strong>\u53c2\u8003\u94fe\u63a5<\/strong><\/p>\n\n\n\n<p><a href=\"https:\/\/blog.csdn.net\/qq_24835087\/article\/details\/122439506\">\u3010openwrt\u3011uloop_run\u8fc7\u7a0b\u5206\u6790_uloop \u6e90\u4ee3\u7801\u5206\u6790-CSDN\u535a\u5ba2<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/blog.csdn.net\/weixin_30388677\/article\/details\/98090433\">openWrt libubox\u7ec4\u4ef6\u4e4buloop\u539f\u7406\u5206\u6790-CSDN\u535a\u5ba2<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u6982\u8ff0<\/h2>\n\n\n\n<p><code>uloop<\/code>\u662f\u4e00\u4e2a\u57fa\u4e8e<code>epoll<\/code>\u5efa\u7acb\u7684\u8f7b\u91cf\u7ea7\u4e8b\u4ef6\u5faa\u73af\u5e93\uff0c\u5b83\u5141\u8bb8\u7a0b\u5e8f\u4ee5\u5355\u7ebf\u7a0b\u3001\u975e\u963b\u585e\u7684\u65b9\u5f0f\u5904\u7406\u591a\u79cd\u4e8b\u4ef6\u6e90\u3002\u4e3b\u8981\u63d0\u4f9b\u4e86<code>timeout<\/code>\u5b9a\u65f6\u5668\u5904\u7406\u548c\u6587\u4ef6\u63cf\u8ff0\u7b26\u89e6\u53d1\u4e8b\u4ef6\u7684\u76d1\u63a7\u7684\u80fd\u529b<\/p>\n\n\n\n<p><code>uloop<\/code>\u7684\u6838\u5fc3\u6570\u636e\u7ed3\u6784\u56f4\u7ed5\u7740\u4e09\u4e2a\u94fe\u8868\u8fdb\u884c\u5c55\u5f00\uff0c\u5206\u522b\u662f\u5b9a\u65f6\u5668\u94fe\u8868\u3001\u5b50\u8fdb\u7a0b\u94fe\u8868\u3001\u4fe1\u53f7\u7ba1\u7406\u94fe\u8868\uff0c\u5176\u4e2d\u4fe1\u53f7\u7ba1\u7406\u94fe\u8868\u4e3b\u8981\u662f\u7528\u4e8e\u7ba1\u7406\u5185\u90e8\u5b9a\u65f6\u4efb\u52a1\u7684\u9500\u6bc1\u52a8\u4f5c<\/p>\n\n\n\n<p>\u6574\u4f53\u67b6\u6784\u7684\u8bbe\u8ba1\u662f\uff0c\u5bf9\u5916\u90e8\u63d0\u4f9b\u521b\u5efa\u76d1\u542c\u53e5\u67c4\u3001\u5b50\u8fdb\u7a0b\u4efb\u52a1\u7684\u5916\u90e8\u63a5\u53e3\u3002\u5e76\u6ce8\u518c\u5916\u90e8\u4fe1\u53f7\u91cf\u5904\u7406\u7684\u56de\u8c03\u51fd\u6570\uff0c\u5728\u5916\u90e8\u6536\u5230\u5916\u90e8\u7684\u4fe1\u53f7\u65f6\uff0c\u7ed3\u675f\u5f53\u524d\u7684\u5b9a\u65f6\u4efb\u52a1\u3002\u5185\u90e8\u7ef4\u62a4\u4e2d\u6bcf\u4e24\u6b21\u5faa\u73af\u4e4b\u95f4\u7684\u95f4\u9694\u7531\u6bcf\u4e2a\u4e8b\u4ef6\u8bbe\u7f6e\u7684\u8d85\u65f6\u65f6\u95f4\u51b3\u5b9a\uff0c\u5e95\u5c42\u662f\u7531<code>epoll_wait<\/code>\u7b49\u5f85\u9884\u8bbe\u597d\u7684\u4e8b\u4ef6<\/p>\n\n\n\n<p>\u5176\u4e2d\u6700\u91cd\u8981\u7684\u6838\u5fc3\u90e8\u5206\u662f\u5b9a\u65f6\u5668\u94fe\u8868\u7684\u7ba1\u7406\u548c\u7ef4\u62a4\uff0c\u6bcf\u4e00\u8f6e\u90fd\u4f1a\u5148\u627e\u5230\u5b9a\u65f6\u4efb\u52a1\u94fe\u8868\u4e2d\u7684\u7b2c\u4e00\u4e2a\u8282\u70b9\uff0c\u8ba1\u7b97\u8fd9\u4e2a\u4efb\u52a1\u548c\u5f53\u524d\u65f6\u95f4\u7684\u63d2\u503c\uff0c\u7528\u8fd9\u4e2a\u63d2\u503c\u4f5c\u4e3a\u4e0b\u4e00\u6b21\u5faa\u73af\u7684\u7b49\u5f85\u65f6\u95f4<\/p>\n\n\n\n<p><strong>\u6574\u4f53\u7ed3\u6784\u5982\u4e0b\u56fe<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/uloop\u6574\u4f53\u67b6\u6784.jpg'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  loading=\"lazy\" decoding=\"async\" width=\"611\" height=\"324\" data-original=\"https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/uloop\u6574\u4f53\u67b6\u6784.jpg\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"\" class=\"wp-image-291\"\/><\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">\u4e3b\u8981\u4f5c\u7528\u548c\u4f7f\u7528\u65b9\u6cd5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u8bbe\u7f6e\u5b9a\u65f6\u4efb\u52a1<\/strong><\/h3>\n\n\n\n<p><code>uloop<\/code>\u53ef\u4ee5\u4f5c\u4e3a\u4e00\u4e2a\u5b9a\u65f6\u5668\u6765\u4f7f\u7528\uff0c\u6267\u884c\u4e00\u4e9b\u5468\u671f\u6027\u6267\u884c\u7684\u5b9a\u65f6\u4efb\u52a1<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;uloop.h&gt;\n\nstruct uloop_timeout timeout;                        \/\/ \u521b\u5efauloop_timeout\u5168\u5c40\u53d8\u91cf\n\nint frequency = 5;                                     \/\/ \u6bcf\u96945\u79d2\u8d85\u65f6\u4e00\u6b21\n\n\/\/ \u8bbe\u7f6e\u5b9a\u65f6\u5668\u56de\u8c03\nstatic void timeout_cb(struct uloop_timeout *t)\n{\n    printf(\"&#91;%s] uloop test \\n\", __FUNCTION__);\n    uloop_timeout_set(t, frequency * 1000);\n}\n\nint main()\n{    \n    uloop_init();                                    \/\/ \u4f7f\u7528\u5e93\u521d\u59cb\u5316    \n    timeout.cb = timeout_cb;                        \/\/ \u8bbe\u7f6e\u5b9a\u65f6\u5668\u8d85\u65f6\u56de\u8c03\n    uloop_timeout_set(&amp;timeout, frequency * 1000);    \/\/ \u8bbe\u7f6e\u4e0b\u6b21\u7684\u8d85\u65f6\u65f6\u95f4\n    uloop_run();\n    uloop_done();\n}<\/code><\/pre>\n\n\n\n<p>\u4e0a\u8ff0\u7a0b\u5e8f\u6548\u679c\uff1a\u6bcf\u9694<code>5S<\/code>\u6253\u5370\u4e00\u6b21<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u76d1\u542c\u53e5\u67c4\u662f\u5426\u6d3b\u8dc3<\/strong><\/h3>\n\n\n\n<p>\u7a0b\u5e8f\u521b\u5efa\u4e86\u4e00\u4e2a<code>TCP 8888<\/code>\u7684\u7aef\u53e3\u5e76\u76d1\u542c\u5b83\uff0c\u4f7f\u7528<code>uloop<\/code>\u8bbe\u7f6e\u56de\u8c03\u5728<code>socket<\/code>\u6d3b\u8dc3\u65f6\u8c03\u7528\u3002\u7a0b\u5e8f\u6574\u4f53\u5206\u4e24\u90e8\u5206\uff0c\u521b\u5efa\u53e5\u67c4\u5e76\u7528<code>uloop<\/code>\u76d1\u542c\u7684<code>server<\/code>\u4fa7\u548c\u8fde\u63a5<code>socket<\/code>\u7684<code>client<\/code>\u7aef<\/p>\n\n\n\n<p><strong>uloop_server\u4fa7\u7a0b\u5e8f\u5982\u4e0b:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;string.h&gt;\n#include &lt;unistd.h&gt;\n#include &lt;sys\/socket.h&gt;\n#include &lt;netinet\/in.h&gt;\n#include &lt;arpa\/inet.h&gt;\n\n#include \"uloop.h\"\n\n#define PORT 8888\n#define MAX_CONN 10\n\nstatic struct uloop_fd server_fd;\n\nstatic inline void close_server_fd(int sock)\n{\n    close(sock);\n}\n\nint create_server_socket()\n{\n    int sock;\n    struct sockaddr_in server_addr;\n\n    sock = socket(AF_INET, SOCK_STREAM, 0);\n    if (sock &lt; 0) {\n        perror(\"socket\");\n        return -1;\n    }\n\n    \/\/ \u8bbe\u7f6e\u5730\u5740\u53ef\u91cd\u7528\n    int reuse = 1;\n    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &amp;reuse, sizeof(reuse)) &lt; 0) {\n        perror(\"setsockopt\");\n        close(sock);\n        return -1;\n    }\n\n    memset(&amp;server_addr, 0, sizeof(server_addr));\n    server_addr.sin_family = AF_INET;\n    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);\n    server_addr.sin_port = htons(PORT);\n\n    if (bind(sock, (struct sockaddr *)&amp;server_addr, sizeof(server_addr)) &lt; 0) {\n        perror(\"bind\");\n        close(sock);\n        return -1;\n    }\n\n    if (listen(sock, MAX_CONN) &lt; 0) {\n        perror(\"listen\");\n        close(sock);\n        return -1;\n    }\n\n    printf(\"Server listening on port %d...\\n\", PORT);\n\n    return sock;\n}\n\n\/\/ \u5f53\u6709\u65b0\u7684\u5ba2\u6237\u7aef\u8fde\u63a5\u65f6\uff0c\u6b64\u56de\u8c03\u51fd\u6570\u5c06\u88ab\u8c03\u7528\nstatic void server_cb(struct uloop_fd *u, unsigned int events)\n{\n    int conn_fd = 0;\n    char client_ip&#91;INET_ADDRSTRLEN] = {0};\n    const char *msg = \"Hello from uloop server!\\n\";\n    struct sockaddr_in client_addr = {0};\n    socklen_t client_len = sizeof(client_addr);\n\n    if (events &amp; ULOOP_READ) {\n        conn_fd = accept(u-&gt;fd, (struct sockaddr *)&amp;client_addr, &amp;client_len);\n        if (conn_fd &lt; 0) {\n            perror(\"accept\");\n            return;\n        }\n\n        inet_ntop(AF_INET, &amp;client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);\n        printf(\"New connection from %s:%d\\n\", client_ip, ntohs(client_addr.sin_port));\n\n        write(conn_fd, msg, strlen(msg));\n        close(conn_fd);\n        printf(\"Connection closed.\\n\");\n    }\n\n    return;\n}\n\nvoid server_run(int sock)\n{\n    uloop_init();\n\n    server_fd.fd = sock;\n    server_fd.cb = server_cb; \n    server_fd.flags = ULOOP_READ; \/\/ \u76d1\u542c\u53ef\u8bfb\u4e8b\u4ef6\n\n    uloop_fd_add(&amp;server_fd, ULOOP_READ);\n    uloop_run();\n\n    uloop_done();\n\n    return;\n}\n\nint main(int argc, char **argv)\n{\n    int sock = create_server_socket();\n\n    server_run(sock);\n    close_server_fd(sock);\n    printf(\"Server shut down.\\n\");\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>clinet\u4fa7\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;string.h&gt;\n#include &lt;unistd.h&gt;\n#include &lt;sys\/socket.h&gt;\n#include &lt;netinet\/in.h&gt;\n#include &lt;arpa\/inet.h&gt;\n\n#define SERVER_IP \"127.0.0.1\"\n#define SERVER_PORT 8888\n#define BUFFER_SIZE 1024\n\nint client_uloop(int sock)\n{\n    struct sockaddr_in server_addr = {0};\n    char buffer&#91;BUFFER_SIZE] = {0};\n\n    memset(&amp;server_addr, 0, sizeof(server_addr));\n    server_addr.sin_family = AF_INET;\n    server_addr.sin_port = htons(SERVER_PORT);\n    if (inet_pton(AF_INET, SERVER_IP, &amp;server_addr.sin_addr) &lt;= 0) {\n        perror(\"inet_pton\");\n        close(sock);\n        return 1;\n    }\n\n    if (connect(sock, (struct sockaddr *)&amp;server_addr, sizeof(server_addr)) &lt; 0) {\n        perror(\"connect\");\n        close(sock);\n        return 1;\n    }\n\n    printf(\"Connected to server at %s:%d\\n\", SERVER_IP, SERVER_PORT);\n\n    ssize_t bytes_received = read(sock, buffer, sizeof(buffer) - 1);\n    if (bytes_received &lt; 0) {\n        perror(\"read\");\n    } else if (bytes_received == 0) {\n        printf(\"Server closed the connection.\\n\");\n    } else {\n        buffer&#91;bytes_received] = '\\0';\n        printf(\"Received message: %s\", buffer);\n    }\n\n    close(sock);\n\n    return 0;\n}\n\n\/\/ \u5ba2\u6237\u7aef\u7a0b\u5e8f\uff1a\u8fde\u63a5\u5230\u670d\u52a1\u5668\u5e76\u63a5\u6536\u6d88\u606f\nvoid do_loop()\n{\n    int sock;\n\n    while (1) {\n        sock = socket(AF_INET, SOCK_STREAM, 0);\n        if (sock &lt; 0) {\n            perror(\"socket\");\n            return;\n        }\n\n        if (client_uloop(sock))\n            perror(\"client_uloop failed\");\n        sleep(1);\n    }\n\n    return;\n}\n\nint main(int argc, char **argv)\n{\n    do_loop();\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u4e0a\u7a0b\u5e8f\u6548\u679c\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>server<\/code>\u4fa7\u521b\u5efa\u4e00\u4e2a<code>TCP 8888<\/code>\u7aef\u53e3\uff0c\u5728\u6709\u65b0\u7684<code>client<\/code>\u7aef\u63a5\u5165\u65f6\u4f1a\u6253\u5370<code>New connection from client_ip:client_port<\/code><\/li>\n\n\n\n<li><code>client<\/code>\u7aef\u7a0b\u5e8f\u7684\u4f5c\u7528\u5df21S\u7684\u95f4\u9694\u4e0d\u65ad\u7684\u53bb\u8fde\u63a5\u672c\u673a\u7684<code>TCP 8888<\/code>\u7aef\u53e3\uff0c\u8fd9\u91cc\u53ea\u662f\u4e3a\u4e86\u6f14\u793a\u7528\uff0c\u5b9e\u9645\u4e0a\u4efb\u4f55\u7a0b\u5e8f\u63a5\u5165<code>server<\/code>\u7aef\u90fd\u662f\u53ef\u4ee5\u7684<\/li>\n<\/ul>\n\n\n\n<p><strong>\u65e5\u5fd7\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># server\u7aef\n.\/server.out\nServer listening on port 8888...\nNew connection from 127.0.0.1:48498\nConnection closed.\nNew connection from 127.0.0.1:48504\nConnection closed.\nNew connection from 127.0.0.1:48516\nConnection closed.\nNew connection from 127.0.0.1:48520\nConnection closed.\nNew connection from 127.0.0.1:48532\nConnection closed.\n\n# client\u7aef\n.\/client.out \nConnected to server at 127.0.0.1:8888\nReceived message: Hello from uloop server!\nConnected to server at 127.0.0.1:8888\nReceived message: Hello from uloop server!\nConnected to server at 127.0.0.1:8888\nReceived message: Hello from uloop server!\nConnected to server at 127.0.0.1:8888\nReceived message: Hello from uloop server!\nConnected to server at 127.0.0.1:8888\nReceived message: Hello from uloop server!<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u8fdb\u7a0b\u76d1\u63a7<\/strong><\/h3>\n\n\n\n<p>\u7a0b\u5e8f\u901a\u8fc7<code>fork<\/code>\u51fd\u6570\u521b\u5efa\u4e86\u4e00\u4e2a\u5b50\u8fdb\u7a0b\u5e76\u5728\u7236\u8fdb\u7a0b\u4e2d\u4f7f\u7528<code>uloop<\/code>\u6765\u76d1\u542c\u5b50\u8fdb\u7a0b\u7684\u72b6\u6001\uff0c\u5f53\u88ab\u76d1\u542c\u7684\u8fdb\u7a0b\u9000\u51fa\u65f6\u5c31\u4f1a\u8c03\u7528\u5bf9\u5e94\u7684\u56de\u8c03\u51fd\u6570<code>process_cb<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;unistd.h&gt;\n#include &lt;sys\/wait.h&gt;\n\n#include \"uloop.h\"\n\nstatic struct uloop_process child_process;\n\n\/\/ \u8fdb\u7a0b\u4e8b\u4ef6\u56de\u8c03\u51fd\u6570\nstatic void process_cb(struct uloop_process *p, int ret)\n{\n    printf(\"Process %d exited with status %d\\n\", p-&gt;pid, WEXITSTATUS(ret));\n}\n\nint main(int argc, char **argv)\n{\n    pid_t pid;\n\n    \/\/ \u521d\u59cb\u5316 uloop\n    uloop_init();\n\n    pid = fork();\n\n    if (pid &lt; 0) {\n        perror(\"fork\");\n        return 1;\n    }\n\n    if (pid == 0) {\n        \/\/ \u5b50\u8fdb\u7a0b\n        printf(\"Child process started, PID: %d\\n\", getpid());\n        sleep(2); \/\/ \u6a21\u62df\u5b50\u8fdb\u7a0b\u5de5\u4f5c\n        printf(\"Child process exiting\\n\");\n        exit(42);\n    }\n\n    \/\/ \u7236\u8fdb\u7a0b\n    printf(\"Parent process, watching child PID: %d\\n\", pid);\n\n    \/\/ \u8bbe\u7f6e uloop_process\n    child_process.cb = process_cb;\n    child_process.pid = pid;\n\n    \/\/ \u5c06\u8fdb\u7a0b\u6dfb\u52a0\u5230 uloop \u76d1\u89c6\n    uloop_process_add(&amp;child_process);\n\n    \/\/ \u542f\u52a8 uloop \u4e8b\u4ef6\u5faa\u73af\n    uloop_run();\n\n    \/\/ \u6e05\u7406 uloop\n    uloop_done();\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u6838\u5fc3\u6570\u636e\u7ed3\u6784<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u5b9a\u65f6\u4efb\u52a1<strong><code>timeouts<\/code>\u94fe\u8868<\/strong><\/h3>\n\n\n\n<p>\u5b9a\u65f6\u5668\u94fe\u8868\uff0c\u8bb0\u5f55\u5b9a\u65f6\u5668\u7684\u72b6\u6001<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* \u5168\u5c40\u53d8\u91cf *\/\nstatic struct list_head timeouts = LIST_HEAD_INIT(timeouts);\n\n\/* \u5b9a\u65f6\u5668\u94fe\u8868\u8282\u70b9 *\/\ntypedef void (*uloop_timeout_handler)(struct uloop_timeout *t);\n\nstruct uloop_timeout\n{\n    struct list_head list;        \/\/\u94fe\u8868\u5934\uff0c\u7528\u4e8e\u94fe\u8868\u64cd\u4f5c\n    bool pending;                \/\/\u6307\u5411\u53e6\u4e00\u4e2a\u5b9a\u65f6\u5668\u7ed3\u6784\u7684\u6307\u9488\uff0c\u7528\u4e8e\u7ba1\u7406\u5c1a\u672a\u5904\u7406\u7684\u5b9a\u65f6\u5668\n\n    uloop_timeout_handler cb;    \/\/\u56de\u8c03\u51fd\u6570\uff0c\u7528\u4e8e\u5904\u7406\u5b9a\u65f6\u5668\u8d85\u65f6\u4e8b\u4ef6\n    struct timeval time;        \/\/\u7528\u4e8e\u5b58\u50a8\u8d85\u65f6\u65f6\u95f4\n};<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\u5b9a\u65f6\u4efb\u52a1\u94fe\u8868\u7ba1\u7406\u63a5\u53e3<\/h4>\n\n\n\n<p><strong><code>uloop_timeout_add<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p>\u65b0\u589e\u5b9a\u65f6\u5668\u8282\u70b9<\/p>\n\n\n\n<p><strong>\u6e90\u4ee3\u7801\u5982\u4e0b<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u9664\u6ce8\u91ca\u5916\uff0c\u6240\u6709\u4ee3\u7801\u5747\u672a\u5220\u6539<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>int uloop_timeout_add(struct uloop_timeout *timeout)\n{\n    struct uloop_timeout *tmp;\n    struct list_head *h = &amp;timeouts;\n\n    if (timeout-&gt;pending)\n        return -1;\n\n    \/*\n     * \u904d\u5386\u6574\u4e2a\u5b9a\u65f6\u94fe\u8868\n     * \u6bd4\u8f83\u9700\u8981\u63d2\u5165\u7684\u8282\u70b9\u7684\u65f6\u95f4\u548c\u5f53\u524d\u94fe\u8868\u5143\u7d20\u7684\u65f6\u95f4\uff0c\u5c06\u8f83\u5927\u7684\u503c\u91c7\u7528\u5c3e\u63d2\u6cd5\u63d2\u5165\n     *\/\n    list_for_each_entry(tmp, &amp;timeouts, list) {\n        if (tv_diff(&amp;tmp-&gt;time, &amp;timeout-&gt;time) &gt; 0) {\n            h = &amp;tmp-&gt;list;\n            break;\n        }\n    }\n\n    list_add_tail(&amp;timeout-&gt;list, h);\n    timeout-&gt;pending = true;\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/timeouts\u94fe\u8868.jpg'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  loading=\"lazy\" decoding=\"async\" width=\"1269\" height=\"544\" data-original=\"https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/timeouts\u94fe\u8868.jpg\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"\" class=\"wp-image-288\"  sizes=\"auto, (max-width: 1269px) 100vw, 1269px\" \/><\/div><\/figure>\n\n\n\n<p>\u6574\u4e2a\u5b9a\u65f6\u5668\u94fe\u8868\u4ee5<code>time<\/code>\u6392\u5e8f\u9075\u5faa\u9012\u589e\u7684\u987a\u5e8f\uff0c\u5c06\u65f6\u95f4\u8f83\u5927\u7684\u5143\u7d20\u63d2\u5165\u5c3e\u90e8<\/p>\n\n\n\n<p><strong><code>uloop_clear_timeouts<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p>\u51fd\u6570\u4e3b\u8981\u4f5c\u7528\u662f\uff0c\u6e05\u7a7a\u5b9a\u65f6\u5668\u94fe\u8868<\/p>\n\n\n\n<p><strong>\u6e90\u4ee3\u7801\u5982\u4e0b<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u9664\u6ce8\u91ca\u5916\uff0c\u6240\u6709\u4ee3\u7801\u5747\u672a\u5220\u6539<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>static void uloop_clear_timeouts(void)\n{\n    struct uloop_timeout *t, *tmp;\n\n    \/* \u904d\u5386\u5b9a\u65f6\u5668\u94fe\u8868 *\/\n    list_for_each_entry_safe(t, tmp, &amp;timeouts, list)\n        uloop_timeout_cancel(t);\n}\n\nint uloop_timeout_cancel(struct uloop_timeout *timeout)\n{\n    if (!timeout-&gt;pending)\n        return -1;\n\n    list_del(&amp;timeout-&gt;list);\n    timeout-&gt;pending = false;\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u904d\u5386\u94fe\u8868\uff0c\u4ece\u94fe\u8868\u4e2d\u5220\u9664\u904d\u5386\u5230\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\uff0c\u5e76\u5c06\u8fdb\u7a0b\u72b6\u6001<code>p-&gt;pending<\/code>\u7f6e\u4e3a<code>flase<\/code><\/p>\n\n\n\n<p><strong><code>uloop_process_timeouts<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p>\u5b9a\u65f6\u5668\u94fe\u8868\u7ba1\u7406<strong>\u6838\u5fc3\u63a5\u53e3<\/strong>\u3002\u904d\u5386\u6574\u4e2a\u94fe\u8868\u6267\u884c\u5df2\u7ecf\u5230\u8fbe\u65f6\u95f4\u7684\u8282\u70b9\u56de\u8c03\uff0c\u5e76\u6e05\u9664\u5b9a\u65f6\u5668<\/p>\n\n\n\n<p><strong>\u6e90\u4ee3\u7801\u5982\u4e0b<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u9664\u6ce8\u91ca\u5916\uff0c\u6240\u6709\u4ee3\u7801\u5747\u672a\u5220\u6539<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>static void uloop_process_timeouts(void)\n{\n    struct uloop_timeout *t;\n    struct timeval tv;\n\n    if (list_empty(&amp;timeouts))\n        return;\n\n    uloop_gettime(&amp;tv);\n    while (!list_empty(&amp;timeouts)) {\n        \/* \u83b7\u53d6\u5b9a\u65f6\u5668\u94fe\u8868\u65f6\u95f4\u548c\u5f53\u524d\u65f6\u95f4\u6bd4\u8f83 *\/\n        t = list_first_entry(&amp;timeouts, struct uloop_timeout, list);\n        if (tv_diff(&amp;t-&gt;time, &amp;tv) &gt; 0)\n            break;\n\n        \/* \u6e05\u9664\u8d85\u65f6\u7684\u5b9a\u65f6\u5668\uff0c\u5e76\u6267\u884c\u5b9a\u65f6\u5668\u56de\u8c03 *\/\n        uloop_timeout_cancel(t);\n        if (t-&gt;cb)\n            t-&gt;cb(t);\n\n    }\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u904d\u5386\u6574\u4e2a\u5b9a\u65f6\u5668\u94fe\u8868\uff0c\u5c06\u65f6\u95f4\u8d85\u8fc7\u5f53\u524d\u65f6\u95f4\u7684\u8282\u70b9\u6e05\u9664\uff0c\u7136\u540e\u6267\u884c\u5bf9\u5e94\u56de\u8c03<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u5b50\u8fdb\u7a0b\u7ba1\u7406<code>processes<\/code>\u94fe\u8868<\/h3>\n\n\n\n<p>\u5c06\u5f85\u68c0\u6d4b\u7684\u5b50\u8fdb\u7a0b\u6ce8\u518c\u540e\u4f1a\u5728\u5b50\u8fdb\u7a0b\u6267\u884c\u7ed3\u675f\u540e\u6267\u884c\u63d0\u524d\u6ce8\u518c\u7684\u56de\u8c03\uff0c\u9700\u8981\u6ce8\u610f\u7684\u662f<strong><code>uloop<\/code>\u4e0d\u652f\u6301\u591a\u7ebf\u7a0b\uff0c\u591a\u7ebf\u7a0b\u4e0b\u4f1a\u51fa\u73b0\u6b7b\u9501\u95ee\u9898<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>static struct list_head processes = LIST_HEAD_INIT(processes);\n\nstruct uloop_process\n{\n    struct list_head list;        \/\/\u94fe\u8868\u5934\uff0c\u7528\u4e8e\u94fe\u8868\u64cd\u4f5c\n    bool pending;                \/\/\u8fdb\u7a0b\u7684\u72b6\u6001\u662f\u5426\u5904\u4e8e\u201c\u5f85\u5904\u7406\u201d\u72b6\u6001\n\n    uloop_process_handler cb;    \/\/\u56de\u8c03\u51fd\u6570\u6307\u9488\n    pid_t pid;                    \/\/\u7ba1\u7406\u7684\u5b50\u8fdb\u7a0b\u7684PID\n};<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\u5b50\u8fdb\u7a0b\u7ba1\u7406\u94fe\u8868\u7ba1\u7406\u63a5\u53e3<\/h4>\n\n\n\n<p><strong><code>uloop_process_add<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p>\u6dfb\u52a0\u65b0\u8282\u70b9<\/p>\n\n\n\n<p><strong>\u6e90\u4ee3\u7801\u5982\u4e0b<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u9664\u6ce8\u91ca\u5916\uff0c\u6240\u6709\u4ee3\u7801\u5747\u672a\u5220\u6539<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>int uloop_process_add(struct uloop_process *p)\n{\n    struct uloop_process *tmp;\n    struct list_head *h = &amp;processes;\n\n    if (p-&gt;pending)\n        return -1;\n\n    list_for_each_entry(tmp, &amp;processes, list) {\n        if (tmp-&gt;pid &gt; p-&gt;pid) {\n            h = &amp;tmp-&gt;list;\n            break;\n        }\n    }\n\n    list_add_tail(&amp;p-&gt;list, h);\n    p-&gt;pending = true;\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u6309\u7167\u5347\u5e8f\u6392\u5e8f\u5c06\u65b0\u8282\u70b9\u63d2\u5165\u94fe\u8868\u4e2d<\/p>\n\n\n\n<p><strong><code>uloop_clear_processes<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p>\u6e05\u7a7a\u94fe\u8868<\/p>\n\n\n\n<p><strong>\u6e90\u4ee3\u7801\u5982\u4e0b<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u9664\u6ce8\u91ca\u5916\uff0c\u6240\u6709\u4ee3\u7801\u5747\u672a\u5220\u6539<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>static void uloop_clear_processes(void)\n{\n    struct uloop_process *p, *tmp;\n\n    list_for_each_entry_safe(p, tmp, &amp;processes, list)\n        uloop_process_delete(p);\n}\n\nint uloop_process_delete(struct uloop_process *p)\n{\n    if (!p-&gt;pending)\n        return -1;\n\n    list_del(&amp;p-&gt;list);\n    p-&gt;pending = false;\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u904d\u5386\u94fe\u8868\uff0c\u4ece\u94fe\u8868\u4e2d\u5220\u9664\u904d\u5386\u5230\u7684\u6bcf\u4e00\u4e2a\u5143\u7d20\uff0c\u5e76\u5c06\u8fdb\u7a0b\u72b6\u6001<code>p-&gt;pending<\/code>\u7f6e\u4e3a<code>flase<\/code><\/p>\n\n\n\n<p><strong><code>uloop_handle_processes<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p>\u5b50\u8fdb\u7a0b\u7ba1\u7406\u6838\u5fc3\u63a5\u53e3\uff0c<\/p>\n\n\n\n<p><strong>\u6e90\u4ee3\u7801\u5982\u4e0b<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u9664\u6ce8\u91ca\u5916\uff0c\u6240\u6709\u4ee3\u7801\u5747\u672a\u5220\u6539<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>static void uloop_handle_processes(void)\n{\n    struct uloop_process *p, *tmp;\n    pid_t pid;\n    int ret;\n\n    do_sigchld = false;\n\n    while (1) {\n        pid = waitpid(-1, &amp;ret, WNOHANG);\n        if (pid &lt; 0 &amp;&amp; errno == EINTR)\n            continue;\n\n        if (pid &lt;= 0)\n            return;\n        \/*\n         * \u904d\u5386\u94fe\u8868\uff0c\u76f4\u5230\u627e\u5230\u4e0e\u5b50\u8fdb\u7a0b\u5339\u914d\u7684pid\n         * \u5220\u9664\u8282\u70b9\u5e76\u6267\u884c\u8282\u70b9\u5bf9\u5e94\u56de\u8c03\n         *\/\n        list_for_each_entry_safe(p, tmp, &amp;processes, list) {\n            if (p-&gt;pid &lt; pid)\n                continue;\n\n            if (p-&gt;pid &gt; pid)\n                break;\n\n            uloop_process_delete(p);\n            p-&gt;cb(p, ret);\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u4fe1\u53f7\u7ba1\u7406<code>signals<\/code>\u94fe\u8868<\/h3>\n\n\n\n<p>\u4fe1\u53f7\u7ba1\u7406\u94fe\u8868,\u4e3b\u8981\u7684\u4f5c\u7528\u662f\u7ba1\u7406\u5916\u90e8\u7684\u4fe1\u53f7\u548c\u5b50\u8fdb\u7a0b\u94fe\u8868\u7684\u4fe1\u53f7<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>static struct list_head signals = LIST_HEAD_INIT(signals);\n\ntypedef void (*uloop_signal_handler)(struct uloop_signal *s);\n\nstruct uloop_signal\n{\n    struct list_head list;            \/\/\u94fe\u8868\u5934\uff0c\u7528\u4e8e\u94fe\u8868\u64cd\u4f5c\n    struct sigaction orig;            \/\/\u4fe1\u53f7\u7684\u539f\u59cb\u5904\u7406\u5668\u7684\u8bbe\u7f6e\n    bool pending;                    \/\/\u6307\u793a\u4fe1\u53f7\u662f\u5426\u5904\u4e8e\u201c\u5f85\u5904\u7406\u201d\u72b6\u6001\n\n    uloop_signal_handler cb;        \/\/\u56de\u8c03\u51fd\u6570\u6307\u9488\n    int signo;                        \/\/\u5b58\u50a8\u4e86\u4fe1\u53f7\u7684\u7f16\u53f7\n};<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\u4fe1\u53f7\u7ba1\u7406\u94fe\u8868\u7ba1\u7406\u63a5\u53e3<\/h4>\n\n\n\n<p><strong><code>uloop_signal_add<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p>\u6dfb\u52a0\u65b0\u7684\u4fe1\u53f7\u5230\u4fe1\u53f7\u7ba1\u7406\u94fe\u8868\u4e2d<\/p>\n\n\n\n<p><strong>\u6e90\u4ee3\u7801\u5982\u4e0b<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u9664\u6ce8\u91ca\u5916\uff0c\u6240\u6709\u4ee3\u7801\u5747\u672a\u5220\u6539<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>int uloop_signal_add(struct uloop_signal *s)\n{\n    struct list_head *h = &amp;signals;\n    struct uloop_signal *tmp;\n    struct sigaction sa;\n\n    if (s-&gt;pending)\n        return -1;\n\n    \/* \u5c06\u4f20\u5165\u7684\u4fe1\u53f7\u6309\u7167\u5347\u5e8f\u6392\u5217\u6dfb\u52a0\u5230\u94fe\u8868\u4e2d *\/\n    list_for_each_entry(tmp, &amp;signals, list) {\n        if (tmp-&gt;signo &gt; s-&gt;signo) {\n            h = &amp;tmp-&gt;list;\n            break;\n        }\n    }\n\n    list_add_tail(&amp;s-&gt;list, h);\n    s-&gt;pending = true;\n\n    sigaction(s-&gt;signo, NULL, &amp;s-&gt;orig);\n\n    if (s-&gt;orig.sa_handler != uloop_signal_wake) {\n        \/* \u8bbe\u7f6e\u4fe1\u53f7\u5904\u7406\u56de\u8c03\u51fd\u6570 uloop_signal_wake *\/\n        sa.sa_handler = uloop_signal_wake;\n        sa.sa_flags = 0;\n        sigemptyset(&amp;sa.sa_mask);\n        \/* \u5c06sa.sa_handle\u7ed1\u5b9a\u4e3a\u4fe1\u53f7s-&gt;signo\u7684\u56de\u8c03\u51fd\u6570 *\/\n        sigaction(s-&gt;signo, &amp;sa, NULL);\n    }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u4fe1\u53f7\u7ba1\u7406\u94fe\u8868\u7684\u63a5\u53e3\uff0c\u4e0e\u5b50\u8fdb\u7a0b\u548c\u5b9a\u65f6\u5668\u7ba1\u7406\u94fe\u8868\u7684\u63a5\u53e3\u975e\u5e38\u76f8\u4f3c\uff0c\u5148\u5c06\u8282\u70b9\u6dfb\u52a0\u5230\u94fe\u8868\u4e2d\u7136\u540e\u8bbe\u7f6e\u56de\u8c03\u3002\u4e0d\u540c\u7684\u662f\u5bf9\u4e8e\u4fe1\u53f7\u5904\u7406\u7684\u56de\u8c03\u51fd\u6570\u4e0d\u80fd\u76f4\u63a5\u8fdb\u884c\u7ed1\u5b9a\uff0c\u9700\u8981\u901a\u8fc7<code>sigaction<\/code>\u7cfb\u7edf\u8c03\u7528\u6765\u5b9e\u73b0<\/p>\n\n\n\n<p><strong><code>uloop_signal_delete<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p><strong>\u6e90\u4ee3\u7801\u5982\u4e0b<\/strong><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u9664\u6ce8\u91ca\u5916\uff0c\u6240\u6709\u4ee3\u7801\u5747\u672a\u5220\u6539<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>int uloop_signal_delete(struct uloop_signal *s)\n{\n    if (!s-&gt;pending)\n        return -1;\n\n    list_del(&amp;s-&gt;list);\n    s-&gt;pending = false;\n\n    if (s-&gt;orig.sa_handler != uloop_signal_wake)\n        sigaction(s-&gt;signo, &amp;s-&gt;orig, NULL);\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u5c06\u8282\u70b9\u4ece\u94fe\u8868\u4e2d\u5220\u9664\uff0c\u5e76\u5c06\u56de\u8c03\u51fd\u6570\u91cd\u7f6e<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u5b9a\u65f6\u4efb\u52a1&amp;\u5b50\u8fdb\u7a0b\u7ba1\u7406\u4efb\u52a1\u6574\u4f53\u6d41\u7a0b<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. \u521d\u59cb\u5316uloop<\/h3>\n\n\n\n<p>\u521d\u59cb\u5316<code>uloop<\/code>\u7684\u52a8\u4f5c\u5728\u5e95\u5c42\u5bf9\u5e94\u7684\u5b9e\u9645\u4e0a\u662f\u521d\u59cb\u5316\u4e86\u4e00\u4e2a\u7ba1\u9053\uff0c\u5e76\u6ce8\u518c<code>epoll<\/code>\u4e8b\u4ef6\u76d1\u542c\u7ba1\u9053\u7684\u8bfb\u7aef\uff1b\u5728<code>uloop<\/code>\u521d\u59cb\u5316\u65f6\u4f1a\u521b\u5efa\u4e00\u4e2a\u7ba1\u9053\uff0c\u7ba1\u9053\u7684\u8f93\u5165\u5b58\u50a8\u5728\u4e00\u4e2a\u5168\u5c40\u53d8\u91cf\u4e2d\u5728\u63a5\u6536\u5230\u5916\u90e8\u4fe1\u53f7\u65f6\u5219\u5199\u8fd9\u4e2a\u53e5\u67c4\uff0c\u7ba1\u9053\u7684\u8f93\u51fa\u7aef\u4f7f\u7528<code>epoll<\/code>\u8fdb\u884c\u76d1\u542c\uff0c\u76d1\u542c\u8d85\u65f6\u65f6\u95f4\u5373<code>uloop<\/code>\u8d85\u65f6\u65f6\u95f4<\/p>\n\n\n\n<p><strong><code>uloop<\/code>\u4e3b\u4f53\u7ed3\u6784\u662f\u4e00\u4e2a\u5927\u5faa\u73af<\/strong>\uff0c\u5728\u6bcf\u4e00\u8f6e\u7684\u5faa\u73af\u4e2d\u53bb\u68c0\u67e5\u6570\u4e2a\u94fe\u8868\u7684\u8282\u70b9\u5143\u7d20\u662f\u5426\u8d85\u65f6\uff0c\u82e5\u8d85\u65f6\u5219\u9700\u8981\u6267\u884c\u5176\u5bf9\u5e94\u7684\u56de\u8c03\u51fd\u6570\uff0c\u5e76\u8bbe\u7f6e\u65b0\u4e00\u8f6e\u7684\u5faa\u73af\u3002\u6bcf\u4e00\u8f6e\u7684\u5faa\u73af\u7684\u4e2d\u95f4<strong>\u95f4\u9694\u65f6\u95f4\u9760<code>epoll<\/code>\u76d1\u542c\u7ba1\u9053\u8f93\u51fa\u7aef\u6765\u963b\u585e\u8fdb\u7a0b<\/strong><\/p>\n\n\n\n<p><strong><code>uloop_init<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int uloop_init(void)\n{\n    if (uloop_init_pollfd() &lt; 0)\n        return -1;\n\n    if (waker_init() &lt; 0) {\n        uloop_done();\n        return -1;\n    }\n\n    uloop_setup_signals(true);\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u672c\u8d28\u662f\u5bf9<code>epoll<\/code>\u7684\u4e00\u5c42\u5c01\u88c5\uff0c<code>uloop_init_pollfd<\/code>\u4e2d\u521b\u5efa<code>epoll<\/code>\u8282\u70b9\uff0c\u540e\u7eed\u5728\u4e0a\u5c42\u8bbe\u7f6e\u4e92\u65a5\u9501\u9632\u6b62\u51fa\u73b0\u6b7b\u9501\u7b49\u95ee\u9898\u3002\u540e\u7eed\u8bbe\u7f6e\u4fe1\u53f7\u91cf\u76d1\u542c\u56de\u8c03\u51fd\u6570<\/p>\n\n\n\n<p>\u5173\u4e8e<code>uloop_init<\/code>\u51fd\u6570\u7684\u5185\u90e8\u5b9e\u73b0\u7684\u5177\u4f53\u8c03\u7528\u6808\u5982\u4e0b<\/p>\n\n\n\n<p><strong>\u51fd\u6570\u8c03\u7528\u6808<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* \u521b\u5efaepoll\u8282\u70b9 *\/\nuloop_init_pollfd()\n    -&gt;epoll_create()\n\nuloop_init()\n    \/* \u521b\u5efa\u7ba1\u9053\uff0c\u4f7f\u7528epoll\u76d1\u542c\u7ba1\u9053\u8f93\u51fa\u7aef *\/\n    -&gt;waker_init()\n        -&gt;pipe(fds)\n        -&gt;uloop_fd_add(&amp;waker_fd, ULOOP_READ)\n            -&gt;register_poll(sock, flags)\n                -&gt;epoll_ctl(poll_fd, op, fd-&gt;fd, &amp;ev)\n    \/* \u6ce8\u518c\u4fe1\u53f7\u56de\u8c03\u51fd\u6570\uff0c\u56de\u8c03\u51fd\u6570\u5199\u5165\u7ba1\u9053\u8f93\u51fa\u7aef *\/\n    -&gt;uloop_setup_signals()\n        -&gt;uloop_install_handler()\n            -&gt;uloop_signal_wake()\n                -&gt;write(waker_pipe, &amp;sigbyte, 1)<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u6d41\u7a0b\u56fe<\/strong><\/p>\n\n\n\n<p>\u6838\u5fc3\u601d\u60f3\u662f\u521b\u5efa\u4e00\u4e2a\u7ba1\u9053\uff0c\u5e76\u6ce8\u518c\u4e00\u90e8\u5206\u5916\u90e8\u4fe1\u53f7\u7684\u56de\u8c03\u3002\u4f7f\u7528<code>epoll<\/code>\u6765\u76d1\u542c\u7ba1\u9053\u7684\u8f93\u51fa\u7aef\uff0c\u800c\u5728\u4fe1\u53f7\u7684\u56de\u8c03\u4e2d\u5411\u7ba1\u9053\u7684\u8f93\u5165\u7aef\u5199\u5165\u6570\u636e\u3002\u5229\u7528\u4e86<code>epoll_wait<\/code>\u7684\u963b\u585e\u7279\u6027\u6765\u4f5c\u4e3a\u5e95\u5c42\u7684\u5b9a\u65f6\u8bbe\u7f6e<\/p>\n\n\n\n<p><strong>\u8fd9\u91cc\u9700\u8981\u7279\u522b\u6ce8\u610f\u7684\u662f<code>uloop_fd_add<\/code>\u51fd\u6570\u662f\u76f4\u63a5\u5bf9\u5916\u66b4\u9732\u7684<\/strong>\uff0c\u5982\u679c\u9700\u8981\u6dfb\u52a0\u5bf9\u67d0\u4e2a\u53e5\u67c4\u7684\u76d1\u542c\u53ef\u76f4\u63a5\u8c03\u7528\u8fd9\u4e2a\u63a5\u53e3<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/uloop_init-scaled.jpg'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1123\" data-original=\"https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/uloop_init-scaled.jpg\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"\" class=\"wp-image-289\"  sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/div><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2. \u8bbe\u7f6e\u5b9a\u65f6\u5668\u8d85\u65f6\u65f6\u95f4<\/h3>\n\n\n\n<p><code>uloop_timeout_set<\/code>\u51fd\u6570<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int uloop_timeout_set(struct uloop_timeout *timeout, int msecs)\n{\n    struct timeval *time = &amp;timeout-&gt;time;\n\n    if (timeout-&gt;pending)\n        uloop_timeout_cancel(timeout);\n\n    uloop_gettime(time);\n\n    time-&gt;tv_sec += msecs \/ 1000;\n    time-&gt;tv_usec += (msecs % 1000) * 1000;\n\n    if (time-&gt;tv_usec &gt; 1000000) {\n        time-&gt;tv_sec++;\n        time-&gt;tv_usec -= 1000000;\n    }\n\n    return uloop_timeout_add(timeout);\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u83b7\u53d6\u5f53\u524d\u7cfb\u7edf\u65f6\u95f4\uff0c\u7136\u540e\u5728\u6b64\u57fa\u7840\u4e0a\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4\uff0c\u5c06\u5f85\u8bbe\u7f6e\u7684\u914d\u7f6e\u6dfb\u52a0\u5230<code>uloop<\/code>\u7684\u94fe\u8868\u4e2d<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. \u6838\u5fc3\u5faa\u73af<\/h3>\n\n\n\n<p><strong>\u6838\u5fc3\u5faa\u73af\u6d41\u7a0b<\/strong><\/p>\n\n\n\n<p><strong>\u51fd\u6570\u8c03\u7528\u6808<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* \u8bbe\u7f6eepoll\u76d1\u542c\u7ba1\u9053\u8f93\u51fa\u7aef\uff0c\u5e76\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4 *\/\nuloop_run()\n    -&gt;uloop_run_timeout(-1)\n        -&gt;next_time = uloop_get_next_timeout();\n        -&gt;uloop_run_events(next_time);\n            -&gt;uloop_fetch_events\n                -&gt;epoll_wait(poll_fd, events, ARRAY_SIZE(events), timeout);<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u6d41\u7a0b\u56fe<\/strong><\/p>\n\n\n\n<p><code>uloop<\/code>\u7684\u4e3b\u5faa\u73af\u5b9e\u9645\u4e0a\u662f\u5728\u76d1\u542c\u53e5\u67c4\u7684\u8f93\u51fa\u7aef\uff0c\u5982\u679c\u6ca1\u6709\u5916\u90e8\u4fe1\u53f7\u5219\u8be5\u7ba1\u9053\u7684\u8f93\u51fa\u7aef\u4f1a\u4e00\u76f4\u4e0d\u6d3b\u8dc3\u3002<code>uloop<\/code>\u4fbf\u662f\u5229\u7528\u4e86<code>epoll<\/code>\u963b\u585e\u5f0f\u7684\u7279\u6027\u6765\u5b9e\u73b0\u5faa\u73af\u7684\u7b49\u5f85\u5e76\u4e14\u5728\u6709\u5916\u90e8\u4e2d\u65ad\u4fe1\u53f7\u65f6\u53ef\u4ee5\u4f18\u96c5\u7684\u9000\u51fa\u8fd9\u4e2a\u5faa\u73af\uff0c\u8fd9\u91cc\u7684\u8d85\u65f6\u65f6\u95f4\u4fbf\u662f\u6839\u636e\u5b9a\u65f6\u5668\u94fe\u8868\u4e2d\u7684\u4e8b\u4ef6\u8ba1\u7b97\uff0c\u5148\u8ba1\u7b97\u8d85\u65f6\u4e8b\u4ef6\u518d\u8bbe\u7f6e<code>epoll<\/code>\u76d1\u542c<\/p>\n\n\n\n<p>\u5728\u4e3b\u5faa\u73af\u4e2d\u6bcf\u4e00\u8f6e\u53bb\u68c0\u67e5\u5b9a\u65f6\u5668\u94fe\u8868\u548c\u8fdb\u7a0b\u7ba1\u7406\u94fe\u8868\uff08\u89c1\u540e\u6587\uff09\u6765\u5b9e\u73b0\u56fa\u5b9a\u95f4\u9694\u4e8b\u4ef6\u5904\u7406\u4e8b\u4ef6\u7684\u6548\u679c<\/p>\n\n\n\n<p><strong>\u5982\u679c\u5728\u5faa\u73af\u7684\u8fc7\u7a0b\u4e2d\u53e5\u67c4\u6d3b\u8dc3\u5219\u4f1a\u76f4\u63a5\u5524\u9192<code>epoll<\/code>\u8fdb\u5165\u4e0b\u4e00\u6b65\u6d41\u7a0b\uff0c\u800c\u4e0d\u662f\u7b49\u5f85\u65f6\u95f4\u7ed3\u675f<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/\u4e3b\u5faa\u73af-scaled.jpg'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1328\" data-original=\"https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/\u4e3b\u5faa\u73af-scaled.jpg\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"\" class=\"wp-image-292\"  sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/div><\/figure>\n\n\n\n<p><strong><code>uloop_run_timeout<\/code>\u51fd\u6570<\/strong><\/p>\n\n\n\n<p>\u6838\u5fc3\u63a5\u53e3\uff0c\u5bf9\u5b9a\u65f6\u5668\u94fe\u8868\u548c\u5b50\u8fdb\u7a0b\u94fe\u8868\u4e2d\u7684<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int uloop_run_timeout(int timeout);\n\nstatic inline int uloop_run(void)\n{\n    return uloop_run_timeout(-1);\n}\n\nint uloop_run_timeout(int timeout)\n{\n    int next_time = 0;\n\n    uloop_run_depth++;\n\n    uloop_status = 0;\n    uloop_cancelled = false;\n    do {\n        uloop_process_timeouts();                \/\/ \u68c0\u6d4buloop\u94fe\u8868\u4e2d\u6240\u6709\u5143\u7d20\uff0c\u5c06\u8d85\u65f6\u7684\u4e8b\u4ef6\u4ece\u94fe\u8868\u4e2d\u5220\u9664\n\n        if (do_sigchld)                            \/\/ \u662f\u5426\u6536\u5230SIGCHLD\u4fe1\u53f7\uff0c\u82e5\u6536\u5230\u5219\u4e3atrue\n            uloop_handle_processes();            \/\/ \u68c0\u67e5\u6240\u6709\u5df2\u7ed3\u675f\u7684\u5b50\u8fdb\u7a0b\uff0c\u5728\u94fe\u8868\u4e2d\u5220\u9664\u8282\u70b9\uff0c\u5e76\u8c03\u7528\u56de\u8c03\u51fd\u6570\u5904\u7406\n\n        if (uloop_cancelled)\n            break;\n\n        next_time = uloop_get_next_timeout();    \/\/ \u8ba1\u7b97\u4e0b\u4e2a\u4e8b\u4ef6\u8d85\u65f6\u79bb\u5f53\u524d\u65f6\u95f4\u591a\u4e45\n        if (timeout &gt;= 0 &amp;&amp; (next_time &lt; 0 || timeout &lt; next_time))\n                next_time = timeout;\n        uloop_run_events(next_time);            \/\/\u901a\u8fc7epoll\u76d1\u542c\u6587\u4ef6\u53e5\u67c4\uff0c\u8d85\u65f6\u65f6\u95f4\u8bbe\u7f6e\u4e3anext_time\n    } while (!uloop_cancelled &amp;&amp; timeout &lt; 0);\n\n    --uloop_run_depth;\n\n    return uloop_status;\n}<\/code><\/pre>\n\n\n\n<p><strong>\u6838\u5fc3\u6d41\u7a0b<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/uloop_run\u6d41\u7a0b-scaled.jpg'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1505\" data-original=\"https:\/\/www.garfield-blog.top\/wp-content\/uploads\/2025\/10\/uloop_run\u6d41\u7a0b-scaled.jpg\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"\" class=\"wp-image-290\"  sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/div><\/figure>\n\n\n\n<p><strong>\u6838\u5fc3\u601d\u60f3<\/strong><\/p>\n\n\n\n<p>\u6700\u5916\u5c42\u8bb0\u5f55\u5faa\u73af\u7684\u6df1\u5ea6\uff0c\u5185\u5c42\u4f7f\u7528\u4e00\u4e2a\u5927\u7684<code>while<\/code>\u5faa\u73af\u4f5c\u4e3a\u51fd\u6570\u7684\u6838\u5fc3\u903b\u8f91\uff0c\u4f7f\u7528<code>uloop_cancelled<\/code>\u548c<code>timeout<\/code>\u5171\u540c\u63a7\u5236\u5faa\u73af<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u76d1\u542c\u53e5\u67c4\u4efb\u52a1\u6574\u4f53\u6d41\u7a0b<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><code>uloop_fd_add<\/code>\u51fd\u6570<\/h3>\n\n\n\n<p>\u7531\u4e8e<code>uloop<\/code>\u5e95\u5c42\u5b9e\u9645\u4e0a\u662f<code>epoll<\/code>\uff0c\u6240\u4ee5\u5982\u679c\u9700\u8981\u76d1\u542c\u67d0\u4e2a\u53e5\u67c4\u5219\u53ef\u4ee5\u76f4\u63a5\u8c03\u7528<code>uloop_fd_add<\/code>\u51fd\u6570\u3002\u8fd9\u4f1a\u5c06\u5f85\u76d1\u542c\u7684\u53e5\u67c4\u6dfb\u52a0\u5230<code>struct uloop_fd<\/code>\u4e2d\uff0c\u5176\u9ed8\u8ba4\u91c7\u7528\u975e\u963b\u585e\u548c\u6c34\u5e73\u89e6\u53d1<\/p>\n\n\n\n<p><code>uloop<\/code>\u4e2d\u4f7f\u7528\u4e86\u4e00\u4e2a\u5168\u5c40\u53d8\u91cf<code>cur_fds<\/code>\u6765\u5b58\u50a8\u5bf9\u5e94\u7684\u4e8b\u4ef6<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>static struct uloop_fd_event cur_fds&#91;ULOOP_MAX_EVENTS];<\/code><\/pre>\n\n\n\n<p><code>uloop_fetch_events<\/code>\u51fd\u6570\u4e2d\u4f1a\u5bf9\u5176\u8fdb\u884c\u8d4b\u503c<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u6b64\u5904\u5220\u9664\u4e86\u5927\u91cf\u5b57\u6bb5\uff0c\u4ec5\u4fdd\u7559\u4e86\u6838\u5fc3\u90e8\u5206\u903b\u8f91<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>static int uloop_fetch_events(int timeout)\n{\n    int n, nfds;\n\n    nfds = epoll_wait(poll_fd, events, ARRAY_SIZE(events), timeout);\n    for (n = 0; n &lt; nfds; ++n) {\n        struct uloop_fd_event *cur = &amp;cur_fds&#91;n];\n        struct uloop_fd *u = events&#91;n].data.ptr;\n        ...\n        cur-&gt;fd = u;\n        ...\n    }\n    return nfds;\n}<\/code><\/pre>\n\n\n\n<p>\u5728<code>uloop_run_events<\/code>\u51fd\u6570\u4e2d\u5bf9\u5176\u8fdb\u884c\u8c03\u7528<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u7b14\u8005\u6ce8\uff1a\u6b64\u5904\u5220\u9664\u4e86\u5927\u91cf\u5b57\u6bb5\uff0c\u4ec5\u4fdd\u7559\u4e86\u6838\u5fc3\u90e8\u5206\u903b\u8f91<\/p>\n<\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code>static void uloop_run_events(int64_t timeout)\n{\n    struct uloop_fd_event *cur;\n    struct uloop_fd *fd;\n\n    while (cur_nfds &gt; 0) {\n        struct uloop_fd_stack stack_cur;\n        unsigned int events;\n\n        cur = &amp;cur_fds&#91;cur_fd++];\n        cur_nfds--;\n\n        fd = cur-&gt;fd;\n\n        stack_cur.fd = fd;\n        fd_stack = &amp;stack_cur;\n        do {\n            stack_cur.events = 0;\n            fd-&gt;cb(fd, events);\n        } while (stack_cur.fd &amp;&amp; events);\n\n        return;\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u53c2\u8003\u94fe\u63a5 \u3010openwrt\u3011uloop_run\u8fc7\u7a0b\u5206\u6790_uloop \u6e90\u4ee3\u7801\u5206\u6790-CSDN\u535a\u5ba2 openWrt  [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[1],"tags":[],"class_list":["post-225","post","type-post","status-publish","format-standard","hentry","category-source-code-analysis"],"_links":{"self":[{"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=\/wp\/v2\/posts\/225","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=225"}],"version-history":[{"count":2,"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=\/wp\/v2\/posts\/225\/revisions"}],"predecessor-version":[{"id":294,"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=\/wp\/v2\/posts\/225\/revisions\/294"}],"wp:attachment":[{"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.garfield-blog.top\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}