【Linux取經路】基礎I/O之重定向的實現原理

在這里插入圖片描述

文章目錄

  • 一、再來理解重定向
    • 1.1 輸出重定向效果演示
    • 1.2 重定向的原理
    • 1.3 dup2
    • 1.4 輸入重定向效果演示
    • 1.5 輸入重定向代碼實現
  • 二、再來理解標準輸出和標準錯誤
    • 2.1 同時對標準輸出和標準錯誤進行重定向
    • 2.2 將標準輸出和標準錯誤重定向到同一個文件
  • 三、再看一切皆文件
  • 四、結語

一、再來理解重定向

1.1 輸出重定向效果演示

在這里插入圖片描述
分析ls 指令是顯示當前目錄下的文件,本質就是將當前目錄下所有的文件名以字符串的形式寫入到顯示器文件。采用輸出重定向 >,將原本應該寫入顯示器文件的內容寫入到了 log.txtx 文件中。

1.2 重定向的原理

在講解重定向原理前,我們需要明確文件描述符的分配規則,即從0下標開始,尋找最小的沒有使用的數組位置,它的下標就是新打開文件的文件描述符。這里沒有使用的意思是該下標里面存的是 NULL,即沒有指向任何一個文件對象。下面通過一段代碼來為大家展示重定向的原理。

// mytest.c
int main()
{close(1);int fd = open(FILE_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0666);if(fd < 0){perror("open");return errno;}const char* str = "Hello Linux!\n";int cnt = 5;while(cnt--){write(1, str, strlen(str));}return 0;
}

代碼分析:上面這段代碼就完美的展示了重定向的原理。首先調用 close 系統調用將 1 號下標對應的文件關閉,關閉的意思就是將 1 下標里的內容置為 NULL,原本 1 下標里面存儲的內容是顯示器文件對象的地址,也就是標準輸出 stdout,緊接著調用 open 打開了一個文件,根據文件描述符的分配規則,新打開的這個文件的文件描述符就是 1,即文件描述符表(file*的數組)1 號下標里面存儲的就是新打開的文件對象的地址。接下來調用 write 接口,向 1 號文件描述符中進行寫入,本來 1 號文件描述符對應的是顯示器文件,原本向顯示器文件中寫入的內容,此時就被寫入到新打開的文件中,沒有向顯示器文件中寫入,因此屏幕上就不會出現字符串,至此整個重定向的過程就結束啦。

在這里插入圖片描述
總結:重定向的本質是對數組下標里面的內容進行修改。
在這里插入圖片描述

1.3 dup2

上面介紹了重定向的原理,下面介紹一下實現重定向的系統調用 dup2

#include <unistd.h>
int dup2(int oldfd, int newfd);

dup2 的具體實現并不是向上面代碼中那樣,先將一個文件描述符關閉,然后緊接著再打開一個文件。dup2 的使用方法是,用戶在調用 dup2 接口前,正常打開一個文件,不用將顯示器文件關閉,此時新打開文件的文件描述符就是 3。接下來調用 dup2 ,將新打開文件的文件描述符作為 oldfd,將顯示器文件的文件描述符也就是 1,作為 newfd。我們知道,文件描述符本質上就是數組下標,dup2 函數中執行的工作就是將 oldfd 下標里存儲的文件對象地址拷貝到 newfd 下標里面,至此重定向工作就完成了。
在這里插入圖片描述
小Tipsdup2 的函數形參有一個誤導,我們可能會覺得新打開文件的描述符是 newfd,其實不然,這里的 newfd 是將要被覆蓋的文件描述符,oldfd 是新打開文件的描述符。

int main()
{// close(1);int fd = open(FILE_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0666);if(fd < 0){perror("open");return errno;}dup2(fd, 1);const char* str = "Hello Linux!\n";int cnt = 5;while(cnt--){write(1, str, strlen(str));}return 0;
}

在這里插入圖片描述
代碼分析:上面就是輸出重定向的實現原理,追加重定向只需要把 O_TRUNC 替換成 O_APPEND

1.4 輸入重定向效果演示

在這里插入圖片描述
分析cat 指令本來是從鍵盤文件中獲取輸入然后寫入顯示器文件中,采用輸入重定向 < 后,是從 log.txt 文件中獲取輸入然后寫入顯示器文件中。

1.5 輸入重定向代碼實現

// 輸入重定向
int main()
{int fd = open(FILE_PATH, O_RDONLY);if(fd < 0){perror("open");}dup2(fd, 0);char str[1024];ssize_t ret = read(fd, str, sizeof(str) - 1);if(ret > 0){str[ret] = '\0';printf("echo: %s", str);}return 0;
}

在這里插入圖片描述
小Tips:進程歷史打開的文件與進行的各種重定向關系都和未來進行的程序替換無關,程序替換并不影響文件訪問。進程打開文件和何種重定向工作,本質上都是進程管理的模塊,而程序替換只會把用戶空間的代碼和數據完全被新程序替換,不會影響到進程管理。

二、再來理解標準輸出和標準錯誤

int main()
{fprintf(stdout, "Standard output messages\n");fprintf(stdout, "Standard output messages\n");fprintf(stdout, "Standard output messages\n");fprintf(stderr, "Standard error messages\n");fprintf(stderr, "Standard error messages\n");fprintf(stderr, "Standard error messages\n");return 0;
}

在這里插入圖片描述
代碼分析> 是輸出重定向,也就是對標準輸出(1號文件描述符)進行重定向。標準錯誤對應的2號文件描述符并沒有進行重定向,因此標準錯誤消息仍然打印在了屏幕上。

2.1 同時對標準輸出和標準錯誤進行重定向

./mytest 1>output.txt 2>error.txt

小Tips:這段代碼就是將1號文件描述符對應的標準輸出文件重定向到 output.txt 文件,將2號文件描述符對應的標準錯誤文件重定向到 error.txt 文件。這樣以來屏幕上就不會有任何輸出。

在這里插入圖片描述

2.2 將標準輸出和標準錯誤重定向到同一個文件

./mytest 1>all.txt 2>&1

在這里插入圖片描述
小Tips:將標準輸出和標準錯誤都重定向到 all.txt 文件中。

三、再看一切皆文件

所有操作計算機的動作,都是通過進程去執行的,所有的訪問文件操作,都是通過進程去實現的,目前所有對文件的操作都依賴于進程。
在這里插入圖片描述

小Tips:所有的外設都被抽象成了文件,每個外設都有自己的讀寫方法,不同的外設讀寫方法一定是不同的。但是我們在對文件進行讀寫操作的時候,始終調用的都是 readwrite 方法,這是因為操作系統為我們提供了一個方法集類型 file_operations,該結構體里面都是函數指針類型,指向外設的各種方法,這就是多態的雛形。所謂的一切皆文件,就是操作系統幫我們封裝了一層文件對象,進程對各種外設的操作,全都變成了對文件的操作。

sszie_t read(int fd)
{task_struct->files->fd_array[fd]->f_op->read();
}

四、結語

今天的分享到這里就結束啦!如果覺得文章還不錯的話,可以三連支持一下,春人的主頁還有很多有趣的文章,歡迎小伙伴們前去點評,您的支持就是春人前進的動力!

在這里插入圖片描述

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

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

相關文章

Elasticsearch從入門到精通-01認識Elasticsearch

Elasticsearch從入門到精通-01認識Elasticsearch &#x1f44f;作者簡介&#xff1a;大家好&#xff0c;我是程序員行走的魚 &#x1f342;博主從本篇正式開始ES學習&#xff0c;希望小伙伴可以一起探討 &#x1f4d6; 本篇主要介紹和大家一塊簡單認識下ES并了解ES中的主要角色…

游戲身份證實名認證接口-C#語言代碼示例

為助力解決網絡游戲中的未成年人過度沉迷、不規范行為以及個人信息安全等問題&#xff0c;翔云API提供了高效、安全的游戲身份證實名認證接口。該接口的目標是通過核驗身份證三要素的方式實現用戶身份的準確驗證&#xff0c;確保玩家真實身份與游戲賬號對應&#xff0c;并有效執…

順序表增刪改查(c語言)

main函數&#xff1a; #include <stdio.h>#include "./seq.h"int main(int argc, const char *argv[]){SeqList* list create_seqList();insert_seqList(list,10);insert_seqList(list,100);insert_seqList(list,12);insert_seqList(list,23);show_seqList(l…

SpringBoot集成Mqtt發送消息

1. MQTT簡介 MQTT是一種物聯網消息協議&#xff0c;為Message Queuing Telemetry Transport的縮寫&#xff0c;即消息隊列傳輸探測&#xff0c;協議基于發布訂閱模式進行通信&#xff0c;有開銷低、帶寬小、輕量的特點&#xff0c;通常應用在物聯網數據采集、移動應用、智能硬…

H5獲取手機相機或相冊圖片兩種方式-Android通過webview傳遞多張照片給H5

需求目的&#xff1a; 手機機通過webView展示H5網頁&#xff0c;在特殊場景下&#xff0c;需要使用相機拍照或者從相冊獲取照片&#xff0c;上傳后臺。 完整流程效果&#xff1a; 如下圖 一、H5界面樣例代碼 使用html文件格式&#xff0c;文件直接打開就可以展示布局&#…

BGP-OSPF防環機制

一、BGP 防環機制 1、AS內部防環&#xff1a;通過IBGP水平分割&#xff0c;IBGP水平分割的基本思想是 不把從IBGP鄰居學到的路由信息發送給其他IBGP鄰居&#xff1b; 2、AS間的防環&#xff1a;通過屬性AS-PATH來實現&#xff0c; 基本思想是&#xff1a;記錄經過的路徑&…

【每日一題】2583. 二叉樹中的第 K 大層和-2024.2.23

題目: 2583. 二叉樹中的第 K 大層和 給你一棵二叉樹的根節點 root 和一個正整數 k 。 樹中的 層和 是指 同一層 上節點值的總和。 返回樹中第 k 大的層和(不一定不同)。如果樹少于 k 層,則返回 -1 。 注意,如果兩個節點與根節點的距離相同,則認為它們在同一層。 示…

canvas水波紋效果,jquery鼠標水波紋插件

canvas水波紋效果&#xff0c;jquery鼠標水波紋插件 效果展示 jQuery水波紋效果&#xff0c;canvas水波紋插件 HTML代碼片段 <div class"scroll04wrap"><h3>發展歷程</h3><div class"scroll04"><p>不要回頭&#xff0c;一…

前端工程Bem架構及其封裝

文章目錄 簡介語法在vue3項目中引用sass創建bem.scss文件修改vite.config.tsvue文件中使用結果 這是我學習記錄的筆記&#xff0c;如有不正&#xff0c;歡迎補充 簡介 首先認識一下什么是bem架構&#xff1f;BEM的意思就是塊&#xff08;block&#xff09;、元素&#xff08;e…

【DDD】學習筆記-發布者—訂閱者模式

在領域設計模型中引入了領域事件&#xff0c;并不意味著就采用了領域事件建模范式&#xff0c;此時的領域事件僅僅作為一種架構或設計模式而已&#xff0c;屬于領域設計模型的設計要素。在領域設計建模階段&#xff0c;如何選擇和設計領域事件&#xff0c;存在不同的模式&#…

nginx-ingress-controller組件中Nginx的版本升級

參考鏈接&#xff1a;https://blog.csdn.net/qq_22824481/article/details/133761302 https://blog.csdn.net/mengfanshaoxia/article/details/127155020 https://blog.csdn.net/weixin_39961559/article/details/87935873 概要 業務區k…

JAVAEE初階 JVM(一)

JVM的熱門話題 一. JVM中的內存區域劃分1.經典筆試題. 二. JVM的類加載機制 一. JVM中的內存區域劃分 1.經典筆試題. 二. JVM的類加載機制

wondows10用Electron打包threejs的項目記錄

背景 電腦是用的mac&#xff0c;安裝了parallels desktop ,想用electron 想同時打包出 蘋果版本和windows版本。因為是在虛擬機里安裝&#xff0c;它常被我重裝&#xff0c;所以記錄一下打包的整個過程。另外就是node生態太活躍&#xff0c;幾個依賴沒記錄具體版本&#xff0…

lora網關智慧工廠三色燈安燈狀態采集鋇錸技術S281

LoRa網關結合鋇錸技術S281模塊在智慧工廠三色燈安燈狀態采集方面具有廣泛的應用前景。智慧工廠的安全生產管理對于企業生產經營至關重要&#xff0c;而三色燈安燈是工廠安全生產管理的重要指示燈&#xff0c;通過LoRa無線通信技術和鋇錸技術S281模塊&#xff0c;可以實現對三色…

android 使用X264編碼視頻

android 使用X264編碼視頻 源碼剛上傳可能審核 源碼下載地址 X264對應部分API介紹 初始化x264_param_t _x264_param new x264_param_t;/*** preset是編碼速度* 可選項"ultrafast", "superfast", "veryfast", "faster", "fa…

使用 package.json 配置代理解決 React 項目中的跨域請求問題

使用 package.json 配置代理解決 React 項目中的跨域請求問題 當我們在開發前端應用時&#xff0c;經常會遇到跨域請求的問題。為了解決這個問題&#xff0c;我們可以通過配置代理來實現在開發環境中向后端服務器發送請求。 在 React 項目中&#xff0c;我們可以使用 package…

MES系統中的手動排產和自動排產-助力生產效率

企業在排產管理中面臨的問題&#xff1a; 大多數的企業在調度排產過程中&#xff0c;都會遇到以下問題。首先是插單非常的多&#xff0c;計劃調整困難&#xff0c;會經常性的發生原材料、零部件的備貨不足。計劃按MRP或庫存展示計算出需求后將產生大量工單&#xff0c;這些工單…

《劍指Offer》筆記題解思路技巧優化_Part_6

《劍指Offer》筆記&題解&思路&技巧&優化_Part_6 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相識&#x1f622;&#x1f622;&#x1f622; 開始刷題&#x1f7e1;1.LCR 168. 丑數—— 丑數&#x1f7e2;2. LCR 16…

Kubernetes服務網絡Ingress網絡模型分析、安裝和高級用法

文章目錄 1、Ingres簡介2、Ingres網絡模型分析3、安裝Ingress4、使用4.1、搭建測試環境4.2、域名訪問4.3、路徑重寫&#xff08;高級用法&#xff09;4.4、流量限制&#xff08;高級用法&#xff09; 5、總結 1、Ingres簡介 Ingress翻譯過來是“入口”的意思&#xff0c;也就是…

切換分支時候IDEA提示:workspace associated with branch feature has been restored

切換分支時候IDEA提示&#xff1a;workspace associated with branch feature has been restored 這個消息是指與"feature"分支關聯的工作區已經恢復。在Git中&#xff0c;工作區是指你當前正在進行修改和編輯的文件和目錄。當你切換分支時&#xff0c;Git會自動將工…