Linux文件:重定向底層實現原理(輸入重定向、輸出重定向、追加重定向)

Linux文件:重定向底層實現原理(輸入重定向、輸出重定向、追加重定向)

  • 前言
  • 一、文件描述符fd的分配規則
  • 二、輸出重定向(>)
  • 三、輸出重定向底層實現原理
  • 四、追加重定向(>>)
  • 五、輸入重定向(<)
  • 六、系統調用dup2
  • 七、標準錯誤stderr存在意義

前言

?在Linux中,操作系統會為每一個文件創建對應的描述結構體對象struct file。該結構體中一定存在3個部分:打開文件的所有屬性、文件的操作集、文件緩沖區(內存)。其中由于馮諾依曼體系決定了,無論對文件進行讀操作還是寫操作,都需要先將數據加載到文件緩存區

?我們在應用層進行對數據讀寫的操作本質上是用戶緩沖區和內核數據緩沖區之間的相互拷貝!!!

一、文件描述符fd的分配規則

  1. 默認情況下,進程會默認打開3個文件:標準輸入、標準輸出、標準錯誤。
  2. 文件描述符的分配規制是:從上往下遍歷查找最小的、未被使用的分別個新的文件!

二、輸出重定向(>)

?下面我們將標準輸出文件關閉,然后創建新的文件;并向新的文件中輸出一些信息。

int main()
{close(1); //將標準輸出文件顯示器關閉int fd = open("log.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);//新創建文件,fd分配為1    if(fd < 0)    {    perror("open");    return 1;                                                         }    printf("what will happen\n");    return 0;
}

在這里插入圖片描述

  • 我們將stdout關閉后,根據文件描述符的分配規則,新創建的文件fd為1。
  • 我們觀察結果發現,原本應該向顯示器打印的消息直接向新創建的文件中寫入。我們將這種現象稱為輸出重定向>!!

三、輸出重定向底層實現原理

?在C中,printf函數只能向標準輸出文件中輸出消息,更準確的說:printf只認文件描述符為1對應的文件

?當我們關閉標準輸出后,新創建的文件所分別的文件描述符fd為1。此時文件描述符表中,下標為1的數組內容由標準輸出替換為新打開的文件log.txt。此時我們調用printf輸出消息時,變為向log.txt文件中寫入!!

所有重定向的本質就是修改特定文件fd的下標內容!!上層fd不變,下層fd指向的內容發生改變!
在這里插入圖片描述

四、追加重定向(>>)

?追加重定向和輸出重定向基本相同,主要在于新創建文件的打開方式從w改為a。在底層上和輸出重定向一樣,都是將fd為1的下標內容替換為新文件即可!!!

int main()
{close(1); //將標準輸出文件顯示器關閉int fd = open("log.txt", O_CREAT | O_WRONLY | O_APPEND, 0666);//新創建文件,fd分配為1    if(fd < 0)    {    perror("open");    return 1;                                                         }    printf("what will happen\n");    return 0;
}

在這里插入圖片描述

五、輸入重定向(<)

?輸入重定向<本質就是將待重定的文件內容替換到fd為0的下標位置。此時我們熟悉的scanf、fputs等函數讀取方式會從鍵盤轉變為新文件。即直接讀取新文件中的內容

int main()
{close(0);   //將顯示器關閉                                                          int fd = open("log.txt", O_RDONLY); //新創建文件fd為0if(fd < 0)    {    perror("open");    return 1;    }    char buffer[1024];    fread(buffer, 1, 1024, stdin);//從文件log.txt中讀寫信息    printf("stdin->fd:%d, %s\n", stdin->_fileno, buffer); return 0;
}

在這里插入圖片描述

  • 在上述代碼執行過程中,沒有出現光標等待我們從鍵盤上輸入信息,而是直接將log.txt中的信息輸出,進一步說明了fd為0的下標內容被替換。

六、系統調用dup2

?上述進行重定向時時進行的fd指向的內容替換,都需要我們手動先將對應的1、2、3號文件關閉,非常麻煩!為此,系統中提供了相關的系統調用接口:dup2

#include <unistd.h>
int dup2(int oldfd, int newfd);//These system calls create a copy of the file descriptor oldfd

【實例】:

int main()
{int fd = open("log.txt", O_CREAT | O_WRONLY | O_TRUNC, 0666);dup2(fd, 1);printf("this is log.txt test\n");  return 0;
}

在這里插入圖片描述

七、標準錯誤stderr存在意義

?標準輸出和標準錯誤都是向顯示器上打印信息。既然都是向同一個硬件進行寫入,為什么還需要標準錯誤的存在?

?在項目實際運行過程中,bug是不可避免的。所以在日志中會記錄很多正確信息和錯誤信息。而stderr存在的意義是將兩者信息分開,將所有的錯誤信息全部寫入標準錯誤文件中,從而降低排除的成本!!

【實例】:

  • 下面我們通過輸出hello stdinhello Stderr來模擬日志中的正確信息和錯誤錯誤信息!
int main()
{fprintf(stdout, "hello stdin\n");                                                       fprintf(stderr, "hello Stderr\n");}

我們情況下,兩者都在顯示器上直接輸出

在這里插入圖片描述


我們也可以通過替換fd=1fd=2的下標對應文件,來將兩者信息分開,分別向兩個文件中寫入
在這里插入圖片描述

  1. 我們也可以將兩種信息全部打印到同一個文件中:1>log.txt 2>&1。 這段代碼的意思是先用log.txt文件fd中的內容替換fd=1下標中的內容,然后&1獲得下標fd=1中保存的數據(即指向log.txt),最后將fd=2對應的內容用fd=1中的內容替換!!即fd=1fd=2都指向了log.txt文件。
  2. 前面講述的輸入重定向、輸出重定向、追加重定向都是簡寫的,原始版本應該和上面重定向一樣,加上對應的fd。例如輸出重定向./myfile > log.txt./myfile 1 > log.txt簡寫。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/12916.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/12916.shtml
英文地址,請注明出處:http://en.pswp.cn/web/12916.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于 vs2019 c++20 規范里的 STL 庫里模板 decay_t<T>

&#xff08;1&#xff09; 這個模板&#xff0c;在庫代碼里非常常見。 decay 英文是“衰弱&#xff0c;消減” 的意思&#xff0c;大概能感覺到就是要簡化模板參數 T 的類型&#xff0c;去掉其上的修飾符。因為常用且復雜&#xff0c;故單獨列出其源碼和注釋。先舉例其應用場景…

LINQ(五) ——使用LINQ進行匿名對象初始化

總目錄 C# 語法總目錄 上一篇&#xff1a;LINQ(四) ——使用LINQ進行對象類型初始化 LINQ 五 ——使用LINQ進行匿名對象初始化 6.2 匿名類型 6.2 匿名類型 可以不用聲明定義一個對象&#xff0c;直接使用new&#xff0c;然后直接賦值即可 string[] names { "Tom",…

動態順序表實現

目錄 1. 順序表的概念 2. 實現的功能 3. 順序表的定義 4.順序表的實現 4.1 seqlist.c 4.2 seqlist.h 4.3 test.c 5. 順序表的優缺點 5.1優點 5.2缺點 1. 順序表的概念 用一段物理地址連續的內存依次存儲數據元素的線性結構 本質就是數組&#xff0c;在數組基礎上要求…

從零手寫實現 tomcat-11-filter 過濾器

創作緣由 平時使用 tomcat 等 web 服務器不可謂不多&#xff0c;但是一直一知半解。 于是想著自己實現一個簡單版本&#xff0c;學習一下 tomcat 的精髓。 系列教程 從零手寫實現 apache Tomcat-01-入門介紹 從零手寫實現 apache Tomcat-02-web.xml 入門詳細介紹 從零手寫…

基于Springboot的學生心理壓力咨詢評判(有報告)。Javaee項目,springboot項目。

演示視頻&#xff1a; 基于Springboot的學生心理壓力咨詢評判&#xff08;有報告&#xff09;。Javaee項目&#xff0c;springboot項目。 項目介紹&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三層體系…

Yalmip使用教程(8)-常見報錯及調試方法

博客中所有內容均來源于自己學習過程中積累的經驗以及對yalmip官方文檔的翻譯&#xff1a;https://yalmip.github.io/tutorials/ 這篇博客將詳細介紹使用yalmip工具箱編程過程中的常見錯誤和相應的解決辦法。 1.optimize的輸出參數 眾所周知&#xff0c;optimize是yalmip用來求…

5.7日學習記錄及相關問題解答

1. 閱讀文章 復習 JAVA基礎——接口&#xff08;全網最詳細教程&#xff09; Java之對象的多態性&#xff08;使用生活中通俗的例子講解&#xff09; 新學 JavaWeb——Servlet&#xff08;全網最詳細教程包括Servlet源碼分析&#xff09; 有用 創建Dynamic Web Project工程&…

PS濾鏡插件Camera Raw 15.4升級,開啟智能修圖

前段時間Adobe 更新了photoshop 的智能AI填充功能&#xff0c;深受很多設計師朋友的喜愛。Camera Raw作為PS的一個濾鏡插件對RAW圖片的處理上面有一定的優勢&#xff0c;Camera Raw 15.4升級了&#xff0c;開啟智能修圖木事&#xff0c;一起來看看吧&#xff01; Camera Raw濾鏡…

【2024華為HCIP831 | 高級網絡工程師之路】刷題日記(18)

個人名片&#xff1a;&#x1faaa; &#x1f43c;作者簡介&#xff1a;一名大三在校生&#xff0c;喜歡AI編程&#x1f38b; &#x1f43b;???個人主頁&#x1f947;&#xff1a;落798. &#x1f43c;個人WeChat&#xff1a;hmmwx53 &#x1f54a;?系列專欄&#xff1a;&a…

ClassificationPrimitive 內部原理

ClassificationPrimitive 內部原理 發明 ClassificationPrimitive的真是個天才。其原理是利用 webgl 的模板緩沖區實現。 渲染兩次, 首先是繪制模板, 然后繪制真正的內容。 示意圖: function createClass() {const { program, uniforms } WebGLProgram.buildPrograms(gl, …

代碼隨想錄算法訓練營第36期DAY22

DAY22 654最大二叉樹 自己做的時候忽略了&#xff1a;nums.length>1的題給條件。所以每次遞歸都要判斷是否size()>1&#xff0c;不要空的。 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *rig…

牛客網刷題 | BC84 牛牛學數列2

目前主要分為三個專欄&#xff0c;后續還會添加&#xff1a; 專欄如下&#xff1a; C語言刷題解析 C語言系列文章 我的成長經歷 感謝閱讀&#xff01; 初來乍到&#xff0c;如有錯誤請指出&#xff0c;感謝&#xff01; 描述 這次牛牛又換了個數…

sql中的exists和in的區別

在SQL中&#xff0c;EXISTS 和 IN 都用于子查詢&#xff0c;但它們的用法和目的有所不同。 ### EXISTS EXISTS 是一個邏輯運算符&#xff0c;用于檢查子查詢是否返回任何行。如果子查詢返回至少一行&#xff0c;那么 EXISTS 子句的結果為 TRUE&#xff1b;否則&#xff0c;結果…

一個用Kotlin編寫簡易的串行任務調度器

引言 由于項目中有處理大量后臺任務并且串行執行的需求&#xff0c;特意寫了一個簡易的任務調度器&#xff0c;方便監控每個任務執行和異常情況&#xff0c;任務之間互不影響。正如上所述&#xff0c;Kotlin中的TaskScheduler類提供了一個強大的解決方案&#xff0c;用于使用S…

「AIGC」Python實現tokens算法

本文主要介紹通過python實現tokens統計,避免重復調用openai等官方api,開源節流。 一、設計思路 初始化tokenizer使用tokenizer將文本轉換為tokens計算token的數量二、業務場景 2.1 首次加載依賴 2.2 執行業務邏輯 三、核心代碼 from transformers import AutoTokenizer imp…

React: memo

React.memo 允許你的組件在 props 沒有改變的情況下跳過重新渲染。 const MemoizedComponent memo(SomeComponent, arePropsEqual?)React 通常在其父組件重新渲染時重新渲染一個組件。你可以使用 memo 創建一個組件&#xff0c;當它的父組件重新渲染時&#xff0c;只要它的新…

centos7服務器采用局域網內筆記本代理上網

一、背景 某臺服務器操作系統是centos 7&#xff0c;不能上網。我想在上面裝個ftp軟件&#xff1a;vsftpd。 二、思路 要安裝這個軟件&#xff0c;有2種方案 1&#xff09;設置該臺centos7可以上網 2&#xff09;離線安裝vsftpd 鑒于各種依賴&#xff0c;萬一因為依賴不全或…

《海峽科技與產業》是什么級別的期刊?是正規期刊嗎?能評職稱嗎?

問題解答 問&#xff1a;《海峽科技與產業》期刊是什么級別&#xff1f; 答&#xff1a;國家級 主管單位&#xff1a;中華人民共和國科學技術部 主辦單位&#xff1a;科技部海峽兩岸科學技術交流中心 問&#xff1a;《海峽科技與產業》影響因子&#xff1f; 答&#xff1a;…

相位;傅里葉變換和傅里葉級數是什么;歐拉公式是什么,和傅里葉關系;

目錄 相位 傅里葉變換公式使用舉例 實際案例 傅里葉變換和傅里葉級數是什么

隨筆:棋友們

我是在小學二年級學會中國象棋的&#xff0c;準確說&#xff0c;是學會象棋的下棋規則的&#xff0c;師傅是二舅。我最早的對手就是同學波仔。波仔比我略早學會象棋&#xff0c;總用連珠炮欺負我&#xff0c;開局幾步棋就把我將死。我不知道怎么破解。輪到我先走時&#xff0c;…