<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Poll on 大飞的博客</title>
    <link>https://www.dafei.me/tags/poll/</link>
    <description>Recent content in Poll on 大飞的博客</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Thu, 14 May 2026 06:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.dafei.me/tags/poll/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>从零写OS（二十六）：poll —— 同时等待多个 fd</title>
      <link>https://www.dafei.me/posts/os-26-poll/</link>
      <pubDate>Thu, 14 May 2026 06:00:00 +0000</pubDate>
      <guid>https://www.dafei.me/posts/os-26-poll/</guid>
      <description>&lt;p&gt;上一章实现了 TTY 输入，但用户程序只能这样等输入：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.read_loop:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;syscall&lt;/span&gt; SYS_READ(fd&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, buf, &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;cmp&lt;/span&gt; rax, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;jle&lt;/span&gt; .read_loop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;问题很明显：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CPU 全速空转&lt;/strong&gt;：没有输入时 &lt;code&gt;SYS_READ&lt;/code&gt; 每次返回 0，进程白白占用 CPU&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无法同时等多个 fd&lt;/strong&gt;：如果既要等 stdin，又要等 pipe，必须串行轮询，任一 fd 都可能饿死&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;poll&lt;/code&gt; 解决这两个问题。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;poll-是什么&#34;&gt;poll 是什么&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;poll(fds[], nfds, timeout)&lt;/code&gt; 是一个系统调用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;传入一组 &lt;code&gt;pollfd_t&lt;/code&gt; 结构，每个描述&amp;quot;我关心 fd X 的什么事件&amp;quot;&lt;/li&gt;
&lt;li&gt;内核检查每个 fd 是否满足条件&lt;/li&gt;
&lt;li&gt;返回就绪的 fd 数量，并在 &lt;code&gt;revents&lt;/code&gt; 里标记哪些事件发生了&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; pollfd {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;   fd;       &lt;span style=&#34;color:#75715e&#34;&gt;// 监听哪个 fd
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;short&lt;/span&gt; events;   &lt;span style=&#34;color:#75715e&#34;&gt;// 关心：POLLIN（可读）/ POLLOUT（可写）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;short&lt;/span&gt; revents;  &lt;span style=&#34;color:#75715e&#34;&gt;// 内核填写：实际发生了什么
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;poll&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; pollfd &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;fds, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; nfds, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; timeout_ms);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有了 poll，程序可以：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;poll([{fd=0, POLLIN}, {fd=pipe_r, POLLIN}], 2, -1)
  → 等到任意一个有数据，才返回
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;实现架构&#34;&gt;实现架构&lt;/h2&gt;
&lt;p&gt;整体分四层：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
