Linux | 红帽认证 | IT技术 | 运维工程师
👇1000人技术交流 备注【公众号】更快通过
1.经典回顾C文件接口
在使用C语言时,我们需要访问文件通常会用到fopen、 fwrite、和fread还有fclose等函数。
1.2 fwrite
比如此时我需要往文件中写入一些信息:
int main(){FILE* fp = fopen(“test.txt”,“w”);if(fp == NULL){perror(“fopen failed”);return 1;}const char* str = “i am yui\n”;int len = strlen(str);int num = 5;while(num–){fwrite(str,len,1,fp);}fclose(fp);return 0;}
讯享网
执行结果:
讯享网:/FILETEST\( cat test.txt</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">i</span> <span class="code-snippet__string">am yui~</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">i</span> <span class="code-snippet__string">am yui~</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">i</span> <span class="code-snippet__string">am yui~</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">i</span> <span class="code-snippet__string">am yui~</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__attr">i</span> <span class="code-snippet__string">am yui~</span></span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><strong><span style="color: rgb(0, 82, 255);font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;font-size: 17px;">1.2 fread</span></strong></span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">下面再来读一读文件中的内容:</span></strong></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="cpp"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><stdio.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><string.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__keyword">int</span> <span class="code-snippet__title">main</span><span class="code-snippet__params">()</span></span></span></code><code><span class="code-snippet_outer">{</span></code><code><span class="code-snippet_outer"> FILE* fp = fopen(<span class="code-snippet__string">"test.txt"</span>,<span class="code-snippet__string">"r"</span>);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span>(!fp)</span></code><code><span class="code-snippet_outer"> {</span></code><code><span class="code-snippet_outer"> perror(<span class="code-snippet__string">"fopen failed"</span>);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">1</span>;</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">const</span> <span class="code-snippet__keyword">char</span>* str = <span class="code-snippet__string">"i am yui~\n"</span>;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">char</span> s[<span class="code-snippet__number">1024</span>];</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">int</span> len = <span class="code-snippet__built_in">strlen</span>(str);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">while</span>(<span class="code-snippet__number">1</span>)</span></code><code><span class="code-snippet_outer"> {</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">ssize_t</span> n = fread(s,<span class="code-snippet__number">1</span>,len,fp);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span>(n == len)</span></code><code><span class="code-snippet_outer"> {</span></code><code><span class="code-snippet_outer"> s[len] = <span class="code-snippet__number">0</span>;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">printf</span>(<span class="code-snippet__string">"%s"</span>,s);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span>(feof(fp))</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">break</span>;</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">0</span>;</span></code><code><span class="code-snippet_outer">}</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 16px;letter-spacing: 1px;">输出结果:</span></strong></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="nginx"><code><span class="code-snippet_outer"><span class="code-snippet__attribute">i</span> am yui<span class="code-snippet__regexp">~</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet_outer">i</span> am yui<span class="code-snippet__regexp">~</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet_outer">i</span> am yui<span class="code-snippet__regexp">~</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet_outer">i</span> am yui<span class="code-snippet__regexp">~</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet_outer">i</span> am yui~</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><strong><span style="color: rgb(0, 82, 255);font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;font-size: 19px;">2. 系统文件I/O</span></strong></span><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;"></span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">除了利用上述C接口,我们还可以采用系统接口来访问文件。</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">系统文件 I/O<span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;color: rgb(214, 214, 214);">(输入/输出)</span>是指在操作系统层面进行文件的读写操作。在 Linux 和其他类 Unix 系统中,系统文件 I/O 通常通过系统调用<span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;color: rgb(214, 214, 214);">(system call)</span>完成。与 C 标准库的文件 I/O 函数<span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;color: rgb(214, 214, 214);">(如 fopen、fread、fwrite)</span>相比,系统文件 I/O 提供了更底层的控制和更高的效率,但操作也稍显复杂。</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">为了更好的理解系统文件I/O,我会用系统接口来实现上面的功能,并进行讲解。</span></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="cpp"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><stdio.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><string.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><unistd.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><sys/types.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><fcntl.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><sys/stat.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__keyword">int</span> <span class="code-snippet__title">main</span><span class="code-snippet__params">()</span></span></span></code><code><span class="code-snippet_outer">{</span></code><code><span class="code-snippet_outer"> umask(<span class="code-snippet__number">0</span>);<span class="code-snippet__comment">//去除限制,防止后续干扰</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">int</span> fd = open(<span class="code-snippet__string">"myfile"</span>,O_WRONLY|O_CREAT,<span class="code-snippet__number">0644</span>);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span>(fd<<span class="code-snippet__number">0</span>)</span></code><code><span class="code-snippet_outer"> {</span></code><code><span class="code-snippet_outer"> perror(<span class="code-snippet__string">"open failed"</span>);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">1</span>;</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">int</span> num = <span class="code-snippet__number">5</span>;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">const</span> <span class="code-snippet__keyword">char</span>* str = <span class="code-snippet__string">"i am yui\n"</span>;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">int</span> len = <span class="code-snippet__built_in">strlen</span>(str);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">while</span>(num--)</span></code><code><span class="code-snippet_outer"> {</span></code><code><span class="code-snippet_outer"> write(fd,str,len);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> close(fd);</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">0</span>;</span></code><code><span class="code-snippet_outer">}</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><strong><span style="color: rgb(0, 82, 255);font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;font-size: 19px;">3. open函数</span></strong></span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">因为现在我们需要用系统接口来打开文件,那么我们会用到open函数而不是fopen函数。</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">open 函数是 Unix 和类 Unix 操作系统中的一个系统调用,用于打开文件并返回一个文件描述符。这个文件描述符用于后续的文件操作,如读、写、关闭等。相比 C 标准库的 fopen 函数,open 提供了更底层的控制,更适合系统级编程。</span></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="cpp"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><sys/types.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><sys/stat.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><fcntl.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__keyword">int</span> <span class="code-snippet__title">open</span><span class="code-snippet__params">(<span class="code-snippet__keyword">const</span> <span class="code-snippet__keyword">char</span> *pathname, <span class="code-snippet__keyword">int</span> flags, <span class="code-snippet__keyword">mode_t</span> mode)</span></span>;</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><strong><span style="color: rgb(0, 82, 255);font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;font-size: 17px;">3.1 参数介绍:</span></strong></span></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li></ul><pre class="code-snippet__js"><code><span class="code-snippet_outer">pathname:要打开的文件的路径。</span></code><code><span class="code-snippet_outer">flags:指定文件打开模式和行为的标志,决定文件的打开方式。</span></code><code><span class="code-snippet_outer">mode:新文件的权限掩码,仅在O_CREAT标志创建文件时生效,指定文件的访问权限。</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;letter-spacing: 1px;">这之中的flags要好好聊聊。</span><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;"></span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">访问模式(必须包含一个):</span></strong></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js"><code><span class="code-snippet_outer">O_RDONLY:只读模式打开文件。</span></code><code><span class="code-snippet_outer">O_WRONLY:只写模式打开文件。</span></code><code><span class="code-snippet_outer">O_RDWR:读写模式打开文件。</span></code><code><span class="code-snippet_outer">O_RDONLY、O_WRONLY 和 O_RDWR 中只能选择一个,它们控制文件的基础读写权限。</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 16px;letter-spacing: 1px;">文件创建和控制:</span></strong></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js"><code><span class="code-snippet_outer">O_CREAT:若文件不存在,则创建文件。此标志常与 mode 参数一起使用来指定文件的权限。</span></code><code><span class="code-snippet_outer">O_EXCL:必须与 O_CREAT 组合使用。如果文件已存在,则返回错误,避免重复创建。这种组合常用于创建唯一文件。</span></code><code><span class="code-snippet_outer">O_TRUNC:如果文件存在,并且是以写模式(O_WRONLY 或 O_RDWR)打开,文件长度会被截断为 0。</span></code><code><span class="code-snippet_outer">O_APPEND:追加模式,写入操作时,文件指针会自动移动到文件末尾,适合日志记录等追加写入的场景。</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 16px;letter-spacing: 1px;">非阻塞和同步控制:</span></strong></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="perl"><code><span class="code-snippet_outer">O_NONBLOCK:以非阻塞模式打开文件。对一些特殊文件(如设备文件)有效,适合需要立即返回结果的场景。</span></code><code><span class="code-snippet_outer">O_SYNC:同步写入模式,确保数据立即写入磁盘。每次 <span class="code-snippet__keyword">write</span> 操作都不会缓存到内存,而是直接刷新到存储设备,适合数据持久性要求高的场景。</span></code><code><span class="code-snippet_outer">O_DSYNC:数据同步,类似 O_SYNC,但只同步数据而不包括文件元数据(如最后修改时间)。</span></code><code><span class="code-snippet_outer">O_RSYNC:同步读模式,和 O_SYNC 类似,但影响的是 <span class="code-snippet__keyword">read</span> 操作。</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;letter-spacing: 1px;">我们需要选择合适的功能将它们进行|的操作,因为底层是用状态压缩来实现的,通过位运算<span style="font-size: 16px;letter-spacing: 1px;color: rgb(214, 214, 214);">(位掩码)</span>来实现,使得每一个标志可以独立设置或清除,而不需要为每种组合单独存储。</span><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;"></span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">在下面的写入操作我们只需要选择O_WRONLY|O_CREAT就可以了。</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="color: rgb(0, 82, 255);"><strong><span style="color: rgb(0, 82, 255);font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;font-size: 17px;">3.2 返回值(文件描述符)</span></strong></span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">成功时,open 返回一个文件描述符<span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;color: rgb(214, 214, 214);">(非负整数)</span>,用于后续的文件操作。</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">失败时返回 -1,并设置 errno 来指示错误原因。</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">这里的返回值也很有说法,</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">文件描述符<span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;color: rgb(214, 214, 214);">(File Descriptor, FD)</span>是操作系统分配的一个整数,用于表示每一个打开的文件或 I/O 资源。在 Unix 和类 Unix 系统<span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;color: rgb(214, 214, 214);">(<span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;color: rgb(214, 214, 214);">如</span> Linux)</span>中,文件描述符是进程和内核之间进行文件或资源操作的桥梁,几乎所有的 I/O 操作都是通过文件描述符来完成的。</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">文件描述符是一个非负整数,每个进程有一个文件描述符表来管理文件描述符。打开文件时,操作系统会分配一个文件描述符,用于标识这个文件。该文件描述符可以用于后续的读、写、关闭操作。文件描述符不仅用于文件,也可以表示其他 I/O 资源,如管道、网络套接字、设备文件等。</span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">每个进程在启动时,通常有三个默认的文件描述符,它们称为标准文件描述符:</span></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="cpp"><code><span class="code-snippet_outer">标准输入(<span class="code-snippet__built_in">stdin</span>):文件描述符为 <span class="code-snippet__number">0</span>,用于从用户或输入源读取数据。</span></code><code><span class="code-snippet_outer">标准输出(<span class="code-snippet__built_in">stdout</span>):文件描述符为 <span class="code-snippet__number">1</span>,用于向终端或输出源输出数据。</span></code><code><span class="code-snippet_outer">标准错误(<span class="code-snippet__built_in">stderr</span>):文件描述符为 <span class="code-snippet__number">2</span>,用于向终端输出错误信息。</span></code></pre></section><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;letter-spacing: 1px;">0,1,2对应的物理设备一般是:</span><span style="font-size: 16px;letter-spacing: 1px;">键盘,显示器,显示器。</span><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;"></span></p><p style="margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 16px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 1px;">了解完这些后,我们就可以直接利用文件描述符来直接向显示屏输出数据了。</span></p><section class="code-snippet__fix code-snippet__js"><ul class="code-snippet__line-index code-snippet__js"><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><pre class="code-snippet__js" data-lang="cpp"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><stdio.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><sys/types.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><sys/stat.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><fcntl.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><string.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><unistd.h></span></span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__keyword">int</span> <span class="code-snippet__title">main</span><span class="code-snippet__params">()</span></span></span></code><code><span class="code-snippet_outer">{</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">char</span> buf[<span class="code-snippet__number">1024</span>];</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">ssize_t</span> s = read(<span class="code-snippet__number">0</span>,buf,<span class="code-snippet__keyword">sizeof</span>(buf));<span class="code-snippet__comment">//从键盘读入数据</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span>(s><span class="code-snippet__number">0</span>)</span></code><code><span class="code-snippet_outer"> {</span></code><code><span class="code-snippet_outer"> buf[s] = <span class="code-snippet__number">0</span>;</span></code><code><span class="code-snippet_outer"> write(<span class="code-snippet__number">1</span>,buf,<span class="code-snippet__built_in">strlen</span>(buf));</span></code><code><span class="code-snippet_outer"> write(<span class="code-snippet__number">2</span>,buf,<span class="code-snippet__built_in">strlen</span>(buf));</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">0</span>;</span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment">//运行结果</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment">/</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment">ubuntu@VM-20-9-ubuntu:~/FILETEST\) https://mp.weixin..com/a.outhello worldhello worldhello world*/
从这段代码我们也可以更加清晰地认识到Linux下的一切皆文件。
一些底层知识:
文件描述符是从0开始地小整数,当我们打开文件时,操作系统在内存中要创建相对应地数据结构来描述目标文件,于是就有了file结构体来表示一个已经打开地文件对象。而进程执行open系统调用,必须让进程和文件关联起来。每一个进程都有一个指针file,指向一张表file_struct该表最重要地部分包含一个指针数组,每个元素都是一个指向文件地指针。本质上文件描述符就是该数组地下标,所以只要拿着文件描述符就可以找到对应地文件。

3.2.1 文件描述符的分配规则
先看代码:
int main(){int fd = open(“myfile”,O_RDONLY);//只读模式打开if(fd>0){printf(”%d\n”,fd);}close(fd);return 0;}//运行结果:/ubuntu@VM-20-9-ubuntu:/FILETEST$ https://mp.weixin..com/a.out3/
结果是3。
那么当我们关闭0这个文件描述符试试看呢?

讯享网int main(){close(0);//关闭文件描述符0int fd = open(“myfile”,O_RDONLY);//只读模式打开if(fd<0){perror(“open”);return 1;}printf(”%d\n”,fd);close(fd);return 0;}//打印结果:/ubuntu@VM-20-9-ubuntu:/FILETEST$ https://mp.weixin..com/a.out0*/
结果是0,你猜到了吗。
由此可见,文件描述符的分配规则:在file_struct数组当中,找到当前没有直接使用的最小的一个下标,作为新的文件描述符。
最后在来看看重定向
3.2.2 重定向
现在我们将标志输出1给关闭了,然后再打开一个文件再往里面写点东西,看看会发生什么。
int main(){close(1);//关闭文件描述符1int fd = open(“myfile”,O_WRONLY|O_CREAT,0644);//写模式打开if(fd<0){perror(“open”);return 1;}printf(“fd:%d\n”,fd);fflush(stdout);close(fd);return 0;}
打开myfile发现,文件中存在fd:1。
也是就说,本该再显示屏中显示的内容被写进了myfile文件。我们把这种现象叫做重定向。常见的重定向>, >>, <
重定向的本质:

4. write函数
write 函数是 Unix 和 Linux 系统中进行文件写入操作的系统调用,用于将数据从用户空间的缓冲区写入到文件或设备(例如文件、管道、网络套接字)中。write 是一种底层 I/O 操作,它绕过标准 I/O 缓冲区,直接写入文件描述符指向的目标,常用于处理系统资源的原始数据读写。
语法:
讯享网ssize_t write(int fd, const void *buf, size_t count);
参数说明:
fd:文件描述符,表示要写入的目标文件或设备(例如 STDOUT_FILENO 表示标准输出)。buf:缓冲区指针,指向要写入的数据。count:要写入的字节数,指定从 buf 中读取多少字节写入 fd。
返回值:
讯享网成功时,返回实际写入的字节数(ssize_t 类型)。失败时,返回 -1,并设置 errno 变量来指示错误原因。
5. read函数

read 是 Unix 和 Linux 系统中的一个系统调用,用于从文件或其他输入资源(如管道、网络套接字等)中读取数据到用户提供的缓冲区中。与 write 相对应,read 直接从文件描述符中获取数据,不经过标准 I/O 缓冲区,适合低级别的 I/O 操作。
语法:
ssize_t read(int fd, void *buf, size_t count);
参数说明:
讯享网fd:文件描述符,表示要读取的文件或输入资源(例如 STDIN_FILENO 表示标准输入)。buf:缓冲区指针,指向读取到的数据将要存放的位置。count:期望读取的字节数,即 buf 的大小。
返回值:
成功时,返回实际读取的字节数(ssize_t 类型)。若返回 0,表示读取到文件末尾(EOF)。失败时,返回 -1,并设置 errno 来指示错误原因。
6. 总结
fopen、fclose、fread、fwrite这些都是C语言标准库的函数,也就是库函数。
open、close、read、write都是系统提供的接口,也就是系统调用接口。
而这部分库函数会区调用系统接口。

可以认为,f*系列的函数,都是对系统的封装,方便二次开发。

课程咨询添加:HCIE666CCIE
↑或者扫描上方二维码↑
你有什么想看的技术点和内容
可以在下方留言告诉小盟哦!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/144049.html