Linux 重定向和緩沖區

序言:

前面在Linux 基礎文件IO操作-CSDN博客這篇博客里說了很多函數無論是在語言層還是在系統調用的方面。在調用系統調用open的時候會返回一個整型,在write傳參的時候第一個參數是一個叫fd的東西,這個是什么東西?這篇博客會詳細解釋這個問題。

Ⅰ、文件描述符

什么是文件描述符?當調用open時成功就會返回一個整數這個就是文件描述符(file descriptor

一、C語言FILE和文件描述符的關系

在語言層我們并沒有看見過文件描述符,我們在C語言中經常用的是文件指針,好像文件指針和文件描述符在一些功能上是相識的,他們之間有什么關系嗎?

在C語言庫中FILE是一個結構體,它的里邊就包含了文件描述符,也就是說FILE是對fd的一層封裝。下面我們來看一段代碼來證明這一點:

在C語言層對系統調用做封裝,用來使用更加方便和提升代碼的可移植性。

下面我們再來看一段代碼:

1 #include<stdio.h>2 #include<string.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<sys/types.h>                                                                                                                                                           6 7 8 int main()9 {10     int fd1 = open("log1.txt",O_WRONLY|O_CREAT|O_TRUNC);11     int fd2 = open("log2.txt",O_WRONLY|O_CREAT|O_TRUNC);12     int fd3 = open("log3.txt",O_WRONLY|O_CREAT|O_TRUNC);13     int fd4 = open("log4.txt",O_WRONLY|O_CREAT|O_TRUNC);14 15     printf("fd1 = %d\n",fd1);16     printf("fd2 = %d\n",fd2);17     printf("fd3 = %d\n",fd3);18     printf("fd4 = %d\n",fd4);19     return 0;20 }

在這里我們會很奇怪為什么我們打開的文件的文件描述符是從3開始而不是從0。當我們的代碼開始運行的時候有三個文件流會默認打開,在C語言中叫stdin,stdout, stderr ,這三個文件流占據著0 ,1 ,2? 下面我們來證明一下:

 1 #include<stdio.h>2 #include<string.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<sys/types.h>6 7 8 int main()9 {10     FILE* fd = fopen("log.txt","w");11 12     printf("stdin = %d\n", stdin->_fileno );                                                                                                                                    13     printf("stdout = %d\n", stdout->_fileno );14     printf("stderr = %d\n", stderr->_fileno );15     printf("log.txt = %d\n", fd->_fileno );16 17 18     fclose(fd);19     return 0;20 }

二、為什么要有文件操作符?

上一個博客我們說到我們要對文件進行管理采用 “先組織,再管理” 的思想所以有了struct_file組織各種文件的各種信息,如何去管理這些結構體呢?

再task_struct中會有一個指針指向指針數組,這些指針數組中放著各個struct_file的指針,這個指針數組就叫做文件描述表,數組的下標就是文件描述符,所以文件描述符就是數組的下標,操作系統通過這些文件描述符就可以去管理文件。

三、文件描述符的分配規則

當一個文件打開的時候就會把它的struct_file指針按照最小且沒有被使用的地址存放,這塊地址的下標作為這個文件的fd返回給用戶。

1 #include<stdio.h>2 #include<string.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<sys/types.h>6 7 8 int main()9 {10     fclose(stdin);11     FILE* fd = fopen("log.txt","w");12     printf("log.txt = %d\n", fd->_fileno );                                                                                                                                     13     printf("stdout = %d\n", stdout->_fileno );14     printf("stderr = %d\n", stderr->_fileno );15 16 17     fclose(fd);18     return 0;19 }

Ⅱ、重定向操作

一、重定向的本質

在linux中可以通過一些指令“ > ,>>? ,?<”實現重定向操作。我們如何去實現重定向換句話來說重定向的本質是什么?我們在上面看見C語言中的stdin,stdout,stderr 的文件操作符分別是0,1,2,如果我們打開一個新的文件那么它的文件描述符就是 3 ,如果我們能將files_struct array[3]里的地址復制一份給files_struct array[1]里,那么也就相當于文件描述符為1指向的是我們打開的是我們打開的文件,怎么去改變這兩個值呢?我們可以用系統調用dup2。

參數中的oldfd是要復制的地址的fd,而newfd是被復制地址的fd。按照我們上面說的例子那么oldfd是 3 我們打開的文件,而newfd是 fd = 1的這個文件。知道這個系統調用了以后我們可以做一個實驗。

下面看一段代碼:

 1 #include<stdio.h>2 #include<string.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<sys/types.h>6 #include<unistd.h>7 8 int main()9 {10     int fd = open("log.txt",O_WRONLY|O_CREAT|O_TRUNC);11     dup2(fd,1);12     close(fd);13     printf("hello dup2\n");                                                                                                                                                     14     return 0;15 }

為什么我們printf沒有向顯示器上打而是向我們的文件里打呢?我們知道stdin,stdout,stderr分別是鍵盤文件,顯示器文件,顯示器文件,他們是固定的fd,在C語言在分裝的函數比如printf,scanf在函數里封裝了fd,所以他們的fd是固定的,那么我們通過更改fd = 1里的指針我們就可以實現輸出重定向和追加重定向,更改fd = 0里的指針可以實現輸入重定向。綜上所述重定向的本質就是對文件描述符表對下標 0,1的改變。

=========================================================================

本篇關于Linux的文件理解與操作的介紹就暫告段落啦,希望能對大家的學習產生幫助,歡迎各位佬前來支持糾正!!!

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

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

相關文章

web登錄頁面

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>簡易登錄頁面</title><style>* {mar…

Java中關于線程池的解析

引語在學習了線程與多線程的相關知識后&#xff0c;我們已經能夠實現在程序中使多個任務并行&#xff0c;但是我們在操作時候&#xff0c;往往每執行一個的任務就需要創建一個新的線程。這種方式在需要執行任務很多時不利于我們對線程的管理&#xff0c;且創建過多線程也非常占…

J2EE模式---前端控制器模式

前端控制器模式基礎概念前端控制器模式&#xff08;Front Controller Pattern&#xff09;是一種結構型設計模式&#xff0c;其核心思想是將應用程序的所有請求集中到一個中央處理器&#xff08;前端控制器&#xff09;進行處理&#xff0c;由它負責接收請求、協調處理流程并返…

模塊加載、ES、TS、Babel 淺析

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

day056-Dockerfile案例與Docker Compose

文章目錄0. 老男孩思想-老男孩名言警句1. Dockerfile指令&#xff1a;ENV與ARG的區別&#xff1f;2. 創建WordPress鏡像2.1 CA證書2.1.1 客戶端訪問HTTPS站點&#xff08;阿里云鏡像源&#xff09;過程2.1.2 查看Windows的CA證書2.1.3 ubuntu查看CA證書是否安裝2.2 準備apt下載…

gcc 源碼分析:從IR-RTL 到匯編輸出

在完成了IR-RTL的優化與寄存器分配后就來到匯編代碼的輸出&#xff1a;實現如下&#xff1a;class pass_final : public rtl_opt_pass { public:pass_final (gcc::context *ctxt): rtl_opt_pass (pass_data_final, ctxt){}/* opt_pass methods: */unsigned int execute (functi…

STC89C52系列單片機內部結構詳解

STC89C52 是基于 MCS-51 內核的增強型單片機&#xff0c;其內部結構集成了多種功能模塊&#xff0c;具備強大的數據處理和控制能力&#xff0c;是嵌入式系統中常用的一種微控制器。本文將結合內部結構框圖&#xff0c;詳細介紹 STC89C52 的各個核心組成部分及其功能作用。一、中…

Linux防火墻管理和基礎服務(FTP/SFTP)

防火墻管理# 開放端口firewalld-cmd --add-port880/tcp --permanent# 移除端口或阻止端口firewalld-cmd --remove-port880/tcp --permanent# 重啟服務systemctl restart firewalld# 查看防火墻開放哪些端口&#xff08;查看當前區域的規則&#xff09;firewall-cmd --lis…

Selenium+Java 自動化測試入門到實踐:從環境搭建到元素操作

在自動化測試領域&#xff0c;Selenium 憑借其強大的跨瀏覽器兼容性和靈活的 API&#xff0c;成為 Web 應用測試的首選工具。而 Java 作為一門穩定且廣泛應用的編程語言&#xff0c;與 Selenium 結合能構建出高效、可維護的自動化測試框架。本文將從環境搭建開始&#xff0c;逐…

Hugging Face 模型的緩存和直接下載有什么區別?

Hugging Face 模型的緩存和直接下載&#xff08;下載到本地文件夾&#xff09;是兩種不同的模型管理方式&#xff0c;它們在使用場景、存儲結構和效率上各有優劣。 以下是它們之間的主要區別&#xff1a; Hugging Face 緩存 (Cache) 當您通過 transformers 庫中的 from_pretrai…

JavaScript AJAX 實現,演示如何將 Token 添加到 Authorization

以下是一個完整的原生 JavaScript AJAX 實現&#xff0c;演示如何將 Token 添加到 Authorization 頭部的示例&#xff1a;基礎實現html復制代碼<!DOCTYPE html> <html> <head><title>AJAX Token 示例</title><script>// 獲取當前用戶的 To…

開發語言的優劣勢對比及主要應用領域分析

開發語言是程序員用來編寫軟件指令的工具。每種語言都有自己的設計哲學、語法&#xff08;規則&#xff09;和應用場景&#xff0c;但沒有“放之四海而皆準”的最佳語言。以下是主流和重要開發語言的介紹&#xff0c;按主要應用領域分類&#xff1a; 一、全能型語言 (可在多個領…

Java學習-------事務失效

在 Java 開發中&#xff0c;事務是保證數據一致性和完整性的關鍵機制&#xff0c;尤其在涉及多步數據庫操作的業務場景中不可或缺。然而&#xff0c;在實際開發過程中&#xff0c;事務常常會出現 “失效” 的情況 —— 預期的回滾沒有發生&#xff0c;數據出現不一致。 Java 事…

JavaScript 01 JavaScript 是什么

1.1 JavaScript 是什么JavaScript 是一門世界上最流行的腳本語言&#xff08;基本所有平臺的所有軟件都會用到它&#xff09;。“1994年&#xff0c;網景公司(Netscape)發布了Navigator瀏覽器0.9版。這是歷史上第一個比較成熟的網絡瀏覽器&#xff0c;轟動一時。但是&#xff0…

Bun v1.2.19發布,node_modules隔離,sql比node快6倍

大家好,我是農村程序員,獨立開發者,行業觀察員,前端之虎陳隨易。我會在這里分享關于 獨立開發、編程技術、思考感悟 等內容,歡迎關注。 技術群與交朋友請在個人網站聯系我,網站 1??:https://chensuiyi.me,網站 2??:https://me.yicode.tech。 如果你覺得本文有用…

【NLP輿情分析】基于python微博輿情分析可視化系統(flask+pandas+echarts) 視頻教程 - 主頁布局實現

大家好&#xff0c;我是java1234_小鋒老師&#xff0c;最近寫了一套【NLP輿情分析】基于python微博輿情分析可視化系統(flaskpandasecharts)視頻教程&#xff0c;持續更新中&#xff0c;計劃月底更新完&#xff0c;感謝支持。今天講解主頁布局實現 視頻在線地址&#xff1a; …

# 微調需要準備哪些環境配置?

微調需要準備哪些環境配置&#xff1f; 如果沒有 GPU&#xff0c;即便是微調較小的大語言模型&#xff08;LLMs&#xff09;&#xff0c;過程也會比較慢。如果你已經有了現成的 GPU&#xff0c;那就可以直接開工了。不過&#xff0c;并不是所有人都能負擔得起 GPU—— 這種情況…

ClickHouse物化視圖避坑指南:原理、數據遷移與優化

摘要ClickHouse物化視圖通過預計算和自動更新機制&#xff0c;顯著提升大數據分析查詢性能&#xff0c;尤其適合高并發聚合場景。本文將深入解析其技術原理、生產實踐中的優化策略&#xff0c;以及數據遷移的實戰經驗。一、物化視圖核心概念ClickHouse的物化視圖(Materialized …

Springboot3整合Elasticsearch8(elasticsearch-java)

1、Elasticsearch的JAVA客戶端選擇 Elasticsearch官方支持的客戶端 客戶端名稱簡介使用建議Elasticsearch Java API Client&#xff08;新客戶端&#xff09;官方推薦的新客戶端&#xff0c;基于 JSON Mapping&#xff08;如 ElasticsearchClient 類&#xff09;&#xff0c;…

OpenCV 官翻8 - 其他算法

文章目錄高動態范圍成像引言曝光序列源代碼示例圖像說明結果色調映射圖像曝光融合附加資源高級圖像拼接 API&#xff08;Stitcher 類&#xff09;目標代碼說明相機模型試用指南圖像拼接詳解 (Python OpenCV >4.0.1)stitching_detailed如何使用背景減除方法目標代碼代碼解析結…