深入解析Linux文件重定向原理與dup2系統調用

????????在Linux中,重定向(Redirection)是一種強大的功能,允許用戶控制命令的輸入來源(stdin)和輸出目標(stdoutstderr)。通過重定向,你可以將命令的輸出保存到文件、從文件讀取輸入,甚至將錯誤信息與正常輸出分離處理。

目錄

一、重定向的原理

1、輸出重定向原理

2、追加重定向原理

3、輸入重定向原理

4、標準輸出流和標準錯誤流雖然都顯示在屏幕上,但二者有什么區別呢?

1. 標準輸出 (stdout) 和標準錯誤輸出 (stderr)

2.?perror("perror")?

函數原型

參數的作用

二、系統調用 dup2

功能說明

返回值

使用注意事項

應用示例


一、重定向的原理

????????理解了文件描述符的概念及其分配規則后,我們就能掌握重定向的原理。通過以下三個示例,你會發現重定向的本質就是改變文件描述符所指向的struct file*對象。

1、輸出重定向原理

所謂輸出重定向,就是將程序原本要輸出到某個文件的數據,轉而輸出到另一個指定文件中。

????????例如,若需將原本輸出到顯示器(文件描述符1)的數據重定向至log.txt文件,可在打開log.txt前先關閉文件描述符1。這樣后續打開log.txt時,系統會自動為其分配文件描述符1,實現輸出重定向:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{close(1);int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);if (fd < 0){perror("open");return 1;}printf("hello world\n");printf("hello world\n");printf("hello world\n");printf("hello world\n");printf("hello world\n");fflush(stdout);close(fd);return 0;
}

運行結果后,我們發現顯示器上并沒有輸出數據,對應數據輸出到了log.txt文件當中:

補充說明:

? ? printf函數默認將數據輸出到標準輸出(stdout)。stdout本質上是一個指向struct FILE結構體的指針(對應下面紅色方框部分),該結構體包含一個文件描述符成員變量。

????????對于stdout而言,這個文件描述符的值固定為1。因此,printf實際上是將數據輸出到文件描述符為1的設備。

????????需要注意的是,C語言的數據并不會立即寫入操作系統內存,而是先存儲在C語言維護的緩沖區中。因此,在使用printf打印數據后,通常需要調用fflush函數來強制刷新緩沖區,確保數據被寫入目標文件。

2、追加重定向原理

????????追加重定向和輸出重定向的唯一區別就是,輸出重定向是覆蓋式輸出數據,而追加重定向是追加式輸出數據。

????????比如,我們希望將原本輸出到"顯示器文件"的數據追加寫入log.txt文件,可以先關閉文件描述符1,再以追加寫入模式打開log.txt。這樣就能實現將數據追加到log.txt的重定向操作:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{close(1);int fd = open("log.txt", O_WRONLY|O_APPEND|O_CREAT, 0666);if(fd < 0){perror("open");return 1;}printf("hello Linux\n");printf("hello Linux\n");printf("hello Linux\n");printf("hello Linux\n");printf("hello Linux\n");fflush(stdout);close(fd);return 0;
}

運行結果后,我們發現對應數據便追加式輸出到了log.txt文件當中:

3、輸入重定向原理

輸入重定向就是,將我們本應該從一個文件讀取數據,現在重定向為從另一個文件讀取數據。

????????例如,若要讓原本從"鍵盤文件"讀取數據的scanf函數改為從log.txt文件讀取,可以在打開log.txt前先關閉文件描述符為0的文件(即"鍵盤文件")。這樣后續打開log.txt時,系統會自動為其分配文件描述符0。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{close(0);int fd = open("log.txt", O_RDONLY | O_CREAT, 0666);if (fd < 0){perror("open");return 1;}char str[40];while (scanf("%s", str) != EOF){printf("%s\n", str);}close(fd);return 0;
}

代碼解析

  1. 關閉標準輸入close(0)?關閉了文件描述符0(標準輸入)。

  2. 打開文件open("log.txt", O_RDONLY | O_CREAT, 0666)?嘗試以只讀模式打開文件log.txt,如果文件不存在則創建。由于文件描述符0已被關閉,新打開的文件會占用最小的可用文件描述符,即0。

  3. 讀取輸入scanf("%s", str)?從文件描述符0(現在是log.txt)讀取數據,直到遇到文件結束符(EOF)。

  4. 輸出內容printf("%s\n", str)?將讀取到的內容打印到標準輸出。

scanf?按空格分隔讀取:

  • 第一次讀取?"hello",打印?hello

  • 第二次讀取?"world",打印?world

  • 第三次讀取?"hello",打印?hello

  • 第四次讀取?"world",打印?world

  • ...

  • 直到遇到?"hello Linux"?時,scanf?會先讀?"hello",再讀?"Linux"。?

運行結果后,我們發現scanf函數將log.txt文件當中的數據都讀取出來了:?

說明一下:
????????scanf函數是默認從stdin讀取數據的,而stdin指向的FILE結構體中存儲的文件描述符是0,因此scanf實際上就是向文件描述符為0的文件讀取數據。?

4、標準輸出流和標準錯誤流雖然都顯示在屏幕上,但二者有什么區別呢?

請看以下示例代碼,它分別向標準輸出流和標準錯誤流打印了兩行字符串:

#include <stdio.h>
int main()
{printf("hello printf\n"); //stdoutperror("perror"); //stderrfprintf(stdout, "stdout:hello fprintf\n"); //stdoutfprintf(stderr, "stderr:hello fprintf\n"); //stderrreturn 0;
}

1. 標準輸出 (stdout) 和標準錯誤輸出 (stderr)

  • stdout(標準輸出):默認輸出到終端(屏幕),通常用于正常程序輸出。

  • stderr(標準錯誤輸出):默認也輸出到終端(屏幕),但專用于錯誤或警告信息,不受重定向影響

2.?perror("perror")?

函數原型
void perror(const char *s);
  • 參數?s:用戶提供的字符串,會作為錯誤消息的前綴。

  • 功能:打印當前?errno?對應的系統錯誤描述,格式為?s: 錯誤描述

  • 作用:向?stderr?輸出錯誤信息。

  • 特點

    • perror?用于打印最近的系統錯誤信息(通過?errno?獲取)。

    • 如果之前沒有發生錯誤,可能輸出?"perror: Success"

    • 始終輸出到?stderr

參數的作用
  • 如果?s?非空,perror?會先輸出?s,后跟冒號和空格,再輸出系統錯誤信息。

  • 如果?s?是空字符串 ("") 或?NULL,則只輸出系統錯誤信息(無前綴)。

直接運行程序,結果很顯然就是在顯示器上輸出四行字符串:

????????從表面上看,標準輸出流和標準錯誤流似乎沒有區別,都會將數據顯示在屏幕上。但當我們嘗試將程序運行結果重定向到log.txt文件時,就會發現不同之處:只有標準輸出的兩行內容被寫入文件,而標準錯誤的兩行信息仍然顯示在屏幕上:

重點:

????????實際上,重定向操作針對的是文件描述符1(標準輸出流),并不會影響文件描述符2(標準錯誤流)!!!!!!


二、系統調用 dup2

????????實現重定向只需復制fd_array數組中的元素。比如,當我們將fd_array[3]的內容復制到fd_array[1]時,由于C語言中stdout對應文件描述符1,這樣輸出就被重定向到了log.txt文件。

????????在Linux操作系統中提供了系統接口dup2,我們日常開發常常使用dup2系統調用來復制文件描述符,完成重定向。dup2的函數原型如下:?

int dup2(int oldfd, int newfd);

功能說明

????????dup2函數將fd_array[oldfd]的內容復制到fd_array[newfd]中。若newfd文件描述符已打開,函數會先將其關閉。

返回值

????????成功時返回newfd,失敗時返回-1。

使用注意事項

  1. 當oldfd為無效文件描述符時,調用失敗且不會關閉newfd對應的文件
  2. 若oldfd有效且newfd等于oldfd,函數直接返回newfd而不執行任何操作

應用示例

????????將log.txt的文件描述符fd和標準輸出描述符1傳入dup2后,fd_array[fd]內容會復制到fd_array[1]。由于標準輸出(stdout)對應文件描述符1,原本輸出到顯示器的內容將被重定向至log.txt文件:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);if (fd < 0){perror("open");return 1;}close(1);dup2(fd, 1);printf("hello printf\n");fprintf(stdout, "hello fprintf\n");return 0;
}

代碼運行后,我們即可發現數據被輸出到了log.txt文件當中:

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

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

相關文章

QGIS制作的儀表盤工程

在QGIS的官方資源庫下載了一個QGIS制作的儀表盤工程&#xff0c;感覺非常炫酷&#xff01;分享給大家&#xff01;下面的儀表盤會將選中的道路數及長度&#xff0c;動態顯示在相應的儀表項中&#xff01;下面的儀表盤會將選中的道路數及長度&#xff0c;動態顯示在相應的儀表項…

Python高級數據類型:集合(Set)

集合是Python中一種非常有用的數據結構&#xff0c;它與列表類似但具有獨特的特性。本文將全面介紹集合的所有知識點&#xff0c;從基礎概念到高級用法&#xff0c;幫助初學者徹底掌握集合的使用。1. 集合簡介1.1 什么是集合&#xff1f;集合&#xff08;Set&#xff09;是Pyth…

【Unity編輯器開發GUI.Window】

Unity GUI.Window 筆記 根據官方文檔2021版本的&#xff0c;點擊鏈接跳轉記錄 概述 GUI.Window 是 Unity IMGUI 系統中用于創建彈出窗口的核心方法&#xff0c;具有以下關鍵特性&#xff1a; 浮動窗口&#xff1a;浮于普通 GUI 控件之上焦點控制&#xff1a;可通過點擊獲得焦…

CAN通信驅動開發注意事項

以下是CAN通信驅動開發的關鍵注意事項相關的整理,涵蓋硬件配置、協議實現、錯誤處理及性能優化等方面: 一、硬件層配置要點 引腳復用與時鐘 確認MCU的CAN控制器引腳是否與GPIO復用,正確配置復用模式。 檢查CAN控制器時鐘源,確保波特率計算基準準確。 收發器(Transceiver)…

CCF編程能力等級認證GESP—C++8級—20250628

CCF編程能力等級認證GESP—C8級—20250628單選題&#xff08;每題 2 分&#xff0c;共 30 分&#xff09;判斷題&#xff08;每題 2 分&#xff0c;共 20 分&#xff09;編程題 (每題 25 分&#xff0c;共 50 分)樹上旅行遍歷計數單選題&#xff08;每題 2 分&#xff0c;共 30…

135. Java 泛型 - 無界通配符

文章目錄135. Java 泛型 - 無界通配符 (?)**1. 什么是無界通配符 (?)&#xff1f;****2. 為什么使用無界通配符&#xff1f;****3. 示例&#xff1a;使用 ? 處理任意列表****? 錯誤示例****? 正確示例****4. 為什么 List<Object> 和 List<?> 不一樣&#xff…

NOIP提高組|2010T1機器翻譯

NOIP2010年提高組第一題:機器翻譯 題目描述 小晨的電腦上安裝了一個機器翻譯軟件,他經常用這個軟件來翻譯英語文章。 這個翻譯軟件的原理很簡單,它只是從頭到尾,依次將每個英文單詞用對應的中文含義來替換。對于每個英文單詞,軟件會先在內存中查找這個單詞的中文含義,如果…

Change Data Capture (CDC) with Kafka Connect:實時數據同步的完整指南

Change Data Capture (CDC) 是一種高效的數據同步技術&#xff0c;能夠捕獲數據庫的變更&#xff08;插入、更新、刪除&#xff09;并實時傳輸到其他系統。結合 Kafka Connect&#xff0c;我們可以構建一個可靠、可擴展的 CDC 管道&#xff0c;實現數據庫與數據湖、數據倉庫或消…

云手機網絡加速全攻略:解決游戲卡頓與APP連接失敗困擾

用云手機玩游戲、掛腳本、跑自動任務&#xff0c;明明后臺顯示在線&#xff0c;但畫面卡頓、操作延遲、甚至APP直接“轉圈圈連不上”&#xff0c;是不是很抓狂&#xff1f;問題出在哪里&#xff1f;云手機不卡&#xff0c;網絡卡&#xff1f;其實&#xff0c;大多數云手機的性能…

從“數字土著”到“數據公民”:K-12數據倫理課程的設計、實施與成效追蹤研究

一、引言 1.1 研究背景與意義 在當今數字時代&#xff0c;信息技術以前所未有的速度滲透到社會的各個領域&#xff0c;深刻地改變了人們的生活、工作和學習方式。K-12 教育作為基礎教育的關鍵階段&#xff0c;也在數字化浪潮的推動下發生著巨大的變革。隨著大數據、人工智能…

LVS詳解

LVS(Linux virtual server)簡介即linux虛擬服務器四層負載均衡基本上都會使用 LVS&#xff0c;據了解 BAT 等大廠都是 LVS 重度使用者&#xff0c;就是因為 LVS 非常出色的性能&#xff0c;能為公司節省巨大的成本。LVS&#xff0c;全稱 Linux Virtual Server 是由國人章文嵩博…

Linux內核設計與實現 - 第5章 系統調用

目錄一、系統調用概述二、系統調用實現機制四、性能優化技術五、常見問題排查六、安全注意事項一、系統調用概述 定義 用戶空間訪問內核功能的唯一合法入口提供硬件抽象接口&#xff0c;保證系統穩定和安全 與API區別 特性系統調用API執行層級內核態用戶態實現方式軟中斷(int …

紙板制造糊機操作

糊機操作技巧:開機流程&#xff1a;首先&#xff0c;一切的一切&#xff0c;要看懂生管&#xff0c;我們要用哪個楞別&#xff0c;再看哪個門幅和材質。 也就是說&#xff0c;一切的一切&#xff0c;要生產了&#xff0c;原紙不能用錯了吧&#xff01; 第一步&#xff1a; 壓壓…

WPF 多窗口分文件實現方案

WPF 多窗口分文件實現方案 項目文件結構 WindowSwitcher/ ├── App.xaml ├── App.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Views/ │ ├── SettingsWindow.xaml │ ├── SettingsWindow.xaml.cs │ ├── DataWindow.xaml │ ├─…

在服務器(ECS)部署 MySQL 操作流程

在部署 MySQL 數據庫之前需要準備好服務器環境。可以通過以下兩種方式來準備部署服務器&#xff1a;云服務器&#xff08;ECS&#xff09;&#xff0c;如&#xff1a;阿里云、華為云、騰訊云等。IDC服務器。 現以阿里云服務器&#xff08;ECS&#xff09;Windows版本來進行部署…

Java File 類詳解:從基礎操作到實戰應用,掌握文件與目錄處理全貌

作為一名 Java 開發工程師&#xff0c;你一定在實際開發中遇到過需要操作文件或目錄的場景&#xff0c;例如&#xff1a;讀寫配置文件、上傳下載、日志處理、文件遍歷、路徑管理等。Java 提供了 java.io.File 類來幫助開發者完成這些任務。本文將帶你全面掌握&#xff1a;File …

嵌入式學習-PyTorch(9)-day25

進入尾聲&#xff0c;一個完整的模型訓練 &#xff0c;點亮的第一個led#自己注釋版 import torch import torchvision.datasets from torch import nn from torch.utils.tensorboard import SummaryWriter import time # from model import * from torch.utils.data import Dat…

用AI做帶貨視頻評論分析進階提分【Datawhale AI 夏令營】

文章目錄回顧賽題優化1??優化2??回顧賽題 模塊內容類型說明/示例賽題背景概述參賽者需構建端到端評論分析系統&#xff0c;實現商品識別、多維情感分析、評論聚類與主題提煉三大任務。商品識別輸入video_desc&#xff08;視頻描述&#xff09; video_tags&#xff08;標簽…

Redis常見數據結構詳細介紹

Redis 作為一款高性能的開源內存數據庫&#xff0c;憑借其豐富多樣的數據結構和出色的性能&#xff0c;在緩存、會話存儲、實時分析等眾多場景中得到了廣泛應用。下面將詳細介紹 Redis 主要的數據結構&#xff0c;包括它們的類型、具體用法和適用場景。1、字符串&#xff08;St…

HAMR硬盤高溫寫入的可靠性問題

熱輔助磁記錄(HAMR)作為突破傳統磁記錄密度極限的下一代存儲技術,其在數據中心大規模應用的核心挑戰在于可靠性保障。 擴展閱讀: 下一個存儲戰場:HAMR技術HDD HAMR技術進入云存儲市場! 漫談HAMR硬盤的可靠性 隨著存儲密度向4Tbpsi邁進,傳統磁記錄技術遭遇"三難困境…