<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>文件 on 子恒的博客</title>
    <link>http://chestnutheng.github.io/tags/%E6%96%87%E4%BB%B6/</link>
    <description>Recent content in 文件 on 子恒的博客</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Thu, 31 Oct 2019 17:25:41 +0800</lastBuildDate>
    <atom:link href="http://chestnutheng.github.io/tags/%E6%96%87%E4%BB%B6/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>[Linux]文件和零拷贝</title>
      <link>http://chestnutheng.github.io/linux_io/</link>
      <pubDate>Thu, 31 Oct 2019 17:25:36 +0800</pubDate>
      <guid>http://chestnutheng.github.io/linux_io/</guid>
      <description>&lt;h2 id=&#34;文件&#34;&gt;文件&lt;/h2&gt;&#xA;&lt;h3 id=&#34;文件描述符&#34;&gt;文件描述符&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;文件描述符：在Linux中，所有的文件都是通过文件描述符引用。fd是一个非负整数。按照惯例，标准输入的fd是0，标准输出的fd是1，标准错误的fd是2。分别作为&lt;code&gt;STDIN_FILENO&lt;/code&gt;、&lt;code&gt;STDOUT_FILENO&lt;/code&gt;、&lt;code&gt;STDERR_FILENO&lt;/code&gt;定义在unistd中。&lt;/li&gt;&#xA;&lt;li&gt;文件描述符的上限：fd的范围是 &lt;code&gt;0 ~ OEPN_MAX-1&lt;/code&gt; 。OPEN_MAX一般是20或者64。这代表一个进程最多打开19或63个文件。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;文件内核api&#34;&gt;文件内核API&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;文件的打开：&lt;code&gt;int open(const char *pathname, int flags)&lt;/code&gt;参数填上要打开的文件的名字（甚至可以不存在），会返回打开的fd。下面是一些常用的选项：&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;O_APPEND 文件将以追加模式打开，每次写操作之前，文件偏移量都会置于文件末尾。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;O_CREAT 创建文件。如果文件已经存在，则会直接打开。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;O_EXCL 和上面的O_CREAT联用时，表示如果文件已经存在，就会失败。可以保证多进程同时创建文件的原子操作。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;O_SYNC 打开文件用于同步I/O。在数据写到磁盘之前写操作不会完成；一般的读操作已是同步的，所以这个标志对读操作没有影响。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;O_NONBLOCK 如果可以，文件将在非阻塞模式下打开。任何其它操作都不会使该进程在I/O中阻塞。这种情况可能只用于FIFO。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;O_DIRECT 打开文件用于直接I/O。将会绕过缓冲区操作。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;文件的关闭：&lt;code&gt;int close(int fd)&lt;/code&gt; 关闭一个文件会释放上面所有的记录锁。一个进程终止后，内核会自动关闭它打开的所有文件。&lt;/li&gt;&#xA;&lt;li&gt;文件定位： &lt;code&gt;off_t lseek(int fd, off_t offset, int whence)&lt;/code&gt; 参数whence指定了偏移地址（开始点&lt;code&gt;SEEK_SET&lt;/code&gt; 当前点&lt;code&gt;SEEK_CUR&lt;/code&gt; 结束点&lt;code&gt;SEET_END&lt;/code&gt;），另一个参数offset是从参考点开始的偏移量（可正可负）。返回新的偏移地址。&lt;/li&gt;&#xA;&lt;li&gt;空洞文件：如果写入一部分之后lseek到后面去写入，中间就会产生一个空洞，实际不占用磁盘大小。&lt;/li&gt;&#xA;&lt;li&gt;文件读取：&lt;code&gt;ssize_t read(int fd, void *buf, size_t nbytes)&lt;/code&gt; 返回读取到的字节数。下面的情况可能使得读取到的字节数少于需要的字节数： 1)再读这么多就到了文件尾 2)读网络缓冲区读完 3)读FIFO管道包含的字节少于需要的长度 4)读终端设备，一次一行&lt;/li&gt;&#xA;&lt;li&gt;文件写入：&lt;code&gt;ssize_t write(int fd, const void* buf, size_t nbytes)&lt;/code&gt; 返回写入的字节数。一般和nbytes相同。&lt;/li&gt;&#xA;&lt;li&gt;文件属性编辑：&lt;code&gt;int fcntl(int fd, int cmd, ... /* arg */ )&lt;/code&gt; 提供了编辑fd属性标志的方法。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;read-buf该设置多大&#34;&gt;read buf该设置多大&lt;/h3&gt;&#xA;&lt;p&gt;在Linux ext4系统上，磁盘块长度&lt;code&gt;st_blksize&lt;/code&gt;为4096字节。测试表明，在4096的整数倍上，读磁盘有更快的速率，可以根据需要选择4096或8192等字节的buf。&lt;br&gt;&#xA;系统为了优化频繁写磁盘的情况，会使用预读取（read ahead）技术，在检测到顺序读时，会比本次读取需要的读出更多的数据，读入缓冲区。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
