Linux系統編程——基礎IO

一些前置知識:

文件 = 屬性 + 內容

文件 分為 打開的文件、未打開的文件

打開的文件:由進程打開,本質是 進程與文件 的關系;維護的文件對象先加載文件屬性,文件內容一般按需加載

未打開的文件:在永久性存儲介質 —— 磁盤上;也需要被管理

C語言文件接口

fopen

打開文件并指定打開方式,返回 FILE* 文件對象指針

r:只讀

w:寫入、但在寫入之前會清空文件;? > 重定向也是使用 w 方法寫入文件

a:追加,在文件結尾寫入; >> 追加方法

fwrite

向已打開的 FILE 文件對象寫入 size 字節的內容

stdin、stdout、stderr

C程序默認啟動時,會打開 3 個標準輸入輸出流,分別是 鍵盤文件 和 2 個顯示器文件

fprintf

向指定文件對象 中寫入

文件相關系統調用接口

未打開的文件存儲在 磁盤上,磁盤是 外設,訪問磁盤上的文件 —— 相當于在 訪問硬件;

幾乎所有的庫,只要是 訪問硬件設備相關,必定封裝了系統調用

因為 操作系統 通過 硬件驅動 管理硬件,并向上層提供 系統調用接口;

open

參數解讀

pathname:文件路徑

int flags:系統提供了設置好的多個 宏 標志位,可以 通過 位或運算 進行組合,以實現不同的 文件打開方法(bit 位級別的 標志位傳遞方式、有點類似位圖了)

mode:以 8 進制的方式 設置被打開文件的權限,但還要經過 umask 權限掩碼的計算( 最終權限 = 起始權限 & (~umask)

返回值:一個較小的非負整數,文件描述符 file descriptor

int fd = open("test.txt", O_WRONLY | O_CREAT, 0666);
if( fd < 0 )
{perror("open error");return 1;
}

close

int fd = open("test.txt", O_WRONLY | O_CREAT, 0666);
if( fd < 0 )
{perror("open error");return 1;
}close(fd);

write

int fd = open("logggggg.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
int size_write = write(fd, "aaaaaaa", 3);	
close(fd);

默認從文件開始寫,但不會清空原有內容,而是覆蓋

小結

C文件相關庫函數 封裝了系統調用 open、write、close

C庫中使用 自定義類型 FILE?類型的文件對象描述打開的文件,而系統調用中 使用 文件描述符 fd

不論什么語言,底層都是這種 封裝系統調用的 模式,向用戶提供 庫函數,以便二次開發

文件描述符 fd

在 Linux 中,文件描述符 就是一個 小整數

當磁盤文件被加載到內存,內核為該進程創建 PCB,接著創建文件描述符表 struct files_struct,其中有 存放文件對象指針的 指針數組 struct file* fd_array[ ] ,接著打開 3 個默認的標準輸入輸出流 stdin、stdout、stderr,接著創建一個 struct file 自定義數據結構 描述被打開文件的屬性;如果一個進程打開多個文件,那就創建多個文件對象 struct file,用 雙鏈表指針 互相組織起來 —— 對文件的操作就變成了對該文件對象的 增刪改查

通過從進程創建 到 打開文件捋一遍之后,文件描述符 fd 就是 文件描述符表 中 指針數組的 下標。

既然已經有文件描述符表來組織管理 打開的文件對象 struct file,那各個 struct file 還用雙鏈表結構組織是否多此一舉?

非也,考慮了如果進程崩掉了之類的意外情況。

通過 文件描述符表 結構,將 內核中的 進程管理模塊 與 文件管理模塊 解耦

注意:除了 內核 默認打開的 3 個標準輸入輸出流文件,其余打開文件對象的指針 struct file* 依次按照文件描述符表的 空閑的 元素位置 進行分配。

用 系統調用 操作 fd

例 read:從文件中讀取 count 字節數據

char buff[100];
ssize_t s = read(0, buff, sizeof(buff));
buff[s] = '\0';
printf("echo : %s\n", buff);

從文件描述符為 0 的文件中讀取 sizeof(buff) 大小的數據,并寫入 buff 開始的緩沖區中:

根據運行結果,回車也被寫入,因為此時 bash 內的緩沖區為 行緩沖方式(見后文描述)

小結

為什么默認打開 stdin、stdout、stderr?

因為 操作系統啟動時,鍵盤、顯示器就已經被 操作系統 識別并打開了,在 其他進程被創建時,只需要將這三個 已經被打開的 文件對象struct file 的地址 填進 文件描述符表 中,使用就 ok。

Linux 中的文件相關 系統調用 只認文件描述符,不同于 C 庫中封裝的自定義類型 FILE(但 FILE 中一定封裝了 文件描述符)

stdout 和 stderr 都指向顯示器文件;

一個文件對象 struct file 可以被多個進程使用,例如 3 個默認的 stdin、stdout、stderr 可以被多個進程同時使用;所以 struct file 中會包含一個屬性:引用計數

引用計數:記錄有幾個文件描述符 指向自己;調用 close 會使該文件對象的 引用計數 減 1,并且將 這個進程的 文件描述符表 中的 對應文件描述符下標 的指針數組 的元素 置空,以供其他打開的文件使用; 當被 close 的文件對象的引用計數為 1時,調用 close 會釋放掉這個 文件對象。

重定向

本質:對進程的 文件描述符表 中的地址 進行內核級別的 拷貝。

文件描述符的分配規則:從文件描述符表的 0 下標開始,尋找空閑位置存放 新文件的 文件對象指針。

輸出重定向

示例:將 本來寫入顯示器文件(文件描述符 1)的內容,寫入 文件描述符為 5 的文件

操作系統提供了 系統調用接口,主要介紹 dup2 :完成 拷貝文件描述符下標對應的 文件對象指針 的工作

int fd = open("fdddddddd.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666 );const char* str = "hello world forever!";//dup2(1, fd);dup2(fd, 1);
write(1, str, strlen(str));

追加重定向

與輸出重定向一樣,只是打開文件時 的 flags 參數,再按位或 O_APPEND,就是向文件中追加內容,而不是 清空掉原文件內容 再寫入

int fd = open("fdddddddd.txt", O_WRONLY | O_CREAT | O_APPEND, 0666 );const char* str = "hello world forever!";//dup2(1, fd);dup2(fd, 1);
write(1, str, strlen(str));

輸入重定向

示例:本來要從 stdin 中讀取數據,可以使用 dup2 系統調用接口,拷貝 某個文件描述符對應的 文件對象指針,轉為 從 另一個文件中讀取數據

int fd = open("fdddddddd.txt", O_CREAT | O_APPEND | O_RDONLY, 0666 );                                                                                                                                    char buff[100];dup2(fd, 0);
ssize_t s = read(0, buff, sizeof(buff));
buff[s] = '\0';printf("%s", buff);

成功將 fddddddd.txt 重定向到 0 號文件描述符,使得本應從 stdin 讀取數據存入 buff,轉為 從 fdddddd.txt 中讀取數據 存入 buff。

:如果把 stdout、stdin、stderr 給重定向,覆蓋掉了,有辦法找到這三個文件,再重定向回來即可恢復

為什么 stdout、stderr 都指向顯示器,應用場景

在分離正常日志與錯誤日志時非常有用:

另外,命令行輸出重定向時,默認被重定向的是 1號 文件描述符 stdout,可以省略不寫。

:程序替換 exce 接口功能,并不影響進程對 文件的訪問。

小結

硬件設備都可以被進程,以 open 打開訪問,因為 Linux 下一切皆文件:

1、內核為 進程創建 PCB —— task_struct,其中包含指針 指向文件描述符表

2、文件描述符表 這個指針數組中 存放著 struct file* —— 文件對象的指針

3、對于所有外設(鍵盤、顯示器、磁盤等硬件)來說,進程在 打開它們并創建對應的 struct file 時,struct file 中有個自定義類型的指針 指向 struct operation_func

4、struct operation_func 中有相應的 讀、寫 的函數指針,不同外設共用相同的?struct operation_func 結構(一般情況下);讀、寫和其他方法的 函數指針指向相應的外設的 具體底層驅動的 函數方法實現,但這些對上層來說,是不用關心的;相同的函數指針 卻指向 不同的方法實現,就像面向對象中的 多態一樣

5、struct operation_func 結構中 有 讀、寫等方法的函數指針,不同外設的 底層驅動的 方法實現,就會用來 初始化這些 函數指針。

對于 C 庫中的?stdin、stdout、stderr:

內核在創建進程時就已經把 0、1、2 這三個描述符指向同一個終端設備

C 庫只是隨后把這三個描述符包裝成 FILE* 變量(stdin、stdout、stderr),并加了一層緩沖而已。

在 Linux 中,鍵盤輸入、屏幕輸出都被抽象成同一個“終端設備文件”,這個終端設備文件既提供讀接口(用戶敲的字符)又提供寫接口(送到屏幕的文字),因此 0、1、2 三個文件描述符實際上都指向同一個 inode(同一個 struct file),只是分別用于讀、寫、寫。

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

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

相關文章

力扣164:最大間距

力扣164:最大間距題目思路代碼題目 給定一個無序的數組 nums&#xff0c;返回 數組在排序之后&#xff0c;相鄰元素之間最大的差值 。如果數組元素個數小于 2&#xff0c;則返回 0 。 您必須編寫一個在「線性時間」內運行并使用「線性額外空間」的算法。 思路 這道題的思路…

Redis類型之Hash

1.hash常用操作 這里還是要強調&#xff0c;redis的類型指的是value的類型。故而這里的hash是把key這一層組織完成以后&#xff0c;到了value這一層&#xff0c;value的其中一種類型還可以是hash。1.1 HSET 和 HGETHSET&#xff1a;設置hash類型的keyHSET key field value [fie…

Apache Pulsar性能與可用性優化實踐指南

Apache Pulsar性能與可用性優化實踐指南 一、技術背景與應用場景 隨著微服務、實時計算和大數據平臺的普及&#xff0c;消息系統承擔了海量數據的傳輸與解耦任務。Apache Pulsar作為新一代分布式消息與流處理系統&#xff0c;擁有多租戶、持久化存儲和靈活一致性的特點&#xf…

工單分類微調訓練運維管理工具原型

簡述需求進展之前&#xff0c;我嘗試用Longformer模型來訓練工單分類系統&#xff0c;但問題很快就暴露出來&#xff1a;Longformer訓練時間長得讓人抓狂&#xff0c;每次訓練只能針對一個租戶的數據&#xff0c;無法快速適配多個租戶的需求。切換一個使用相同標簽的租戶還能夠…

@CacheConfig??當前類中所有緩存方法詳解

CacheConfig??當前類中所有緩存方法詳解在 Spring Cache 抽象中&#xff0c;CacheConfig 是一個??類級別注解??&#xff0c;用于為??當前類中的所有緩存方法&#xff08;如 Cacheable、CachePut、CacheEvict&#xff09;提供默認配置??。其核心作用是??避免在每個方…

正確使用SQL Server中的Hint(10)—Hint簡介與Hint分類及語法(1)

9.5. 正確使用Hint 9.5.1. Hint簡介 與Oracle等其他關系庫類似,SQL Server中,也提供了諸多Hint用于支持SQL調優,那就是通過正確應用Hint技術,可以指示CBO為SQL語句產生和選擇最合理而高效的查詢計劃。Hint確實可以做到很容易的對CBO產生影響,但因為多數場景中,CBO都能為…

Redis的分布式序列號生成器原理

Redis 分布式序列號生成器的核心原理是利用 Redis 的原子操作和高性能特性&#xff0c;在分布式系統中生成全局唯一、有序的序列號。其設計通常結合業務需求&#xff08;如有序性、長度限制、高并發&#xff09;&#xff0c;通過 Redis 的原子命令&#xff08;如 INCR、INCRBY&…

2025年SEVC SCI2區,基于深度強化學習與模擬退火的多無人機偵察任務規劃,深度解析+性能實測

目錄1.摘要2.問題定義3.SA-NNO-DRL方法4.結果展示5.參考文獻6.算法輔導應用定制讀者交流1.摘要 無人機&#xff08;UAV&#xff09;因其高自主性和靈活性&#xff0c;廣泛應用于偵察任務&#xff0c;多無人機任務規劃在交通監控和數據采集等任務中至關重要&#xff0c;但現有方…

汽車娛樂信息系統域控制器的網絡安全開發方案

引言1.1 項目背景隨著汽車行業的快速發展和智能化、網聯化的趨勢日益明顯&#xff0c;汽車娛樂信息系統&#xff08;In-Vehicle Infotainment System&#xff0c;IVIS&#xff09;已經成為現代汽車的重要組成部分。汽車娛樂信息系統不僅提供了豐富的多媒體功能&#xff0c;如音…

【論文閱讀】Deep Adversarial Multi-view Clustering Network

摘要多視圖聚類通過挖掘多個視圖之間的共同聚類結構&#xff0c;近年來受到了越來越多的關注。現有的大多數多視圖聚類算法使用淺層、線性嵌入函數來學習多視圖數據的公共結構。然而&#xff0c;這些方法無法充分利用多視圖數據的非線性特性&#xff0c;而這種特性對于揭示復雜…

Redis - 使用 Redis HyperLogLog 進行高效基數統計

文章目錄引言HyperLogLog 工作原理Spring Boot 集成 Redis1. 添加依賴2. 配置 Redis 連接3. Redis 配置類HyperLogLog 實戰應用1. 基礎操作服務類2. 網站日活躍用戶統計3. 性能測試與誤差分析應用場景分析適用場景不適用場景性能優化技巧與傳統方案對比結論引言 在數據分析和監…

後端開發技術教學(三) 表單提交、數據處理

上回&#xff1a;後端開發技術教學(二) 條件指令、循環結構、定義函數 -CSDN博客 必要資源&#xff1a; trae中文版下載網址: TRAE - The Real AI Engineer phpStudy 2018 : phpStudy - Windows 一鍵部署 PHP 開發環境 小皮出品 目錄 一、表單提交 1.1 get & post 1.…

Python訓練Day39

浙大疏錦行 圖像數據的格式&#xff1a;灰度和彩色數據模型的定義顯存占用的4種地方 模型參數梯度參數優化器參數數據批量所占顯存神經元輸出中間狀態 batchisize和訓練的關系 一、 圖像數據的介紹 圖像數據&#xff0c;相較于結構化數據&#xff08;表格數據&#xff09;他的特…

十八、MySQL-DML-數據操作-插入(增加)、更新(修改)、刪除

DML數據操作添加數據更新(修改)數據刪除數據總結代碼&#xff1a; -- DML:數據操作語言-- -- DML:插入數據-insert -- 1.為tb_emp表的username,name&#xff0c;gender 字股插入值insert into tb_emp(username,name,gender,create_time,update_time) values (Toki,小時,2,now()…

Linux 安裝 JDK 8u291 教程(jdk-8u291-linux-x64.tar.gz 解壓配置詳細步驟)?

一、準備工作 ?下載 JDK 安裝包? 去 Oracle 官網或者可信的鏡像站下載&#xff1a; ?jdk-8u291-linux-x64.tar.gz? &#xff08;這是一個壓縮包&#xff0c;不是安裝程序&#xff0c;解壓就能用&#xff09; ?jdk-8u291-linux-x64.tar.gz?下載鏈接&#xff1a;https://pa…

藍橋杯----鎖存器、LED、蜂鳴器、繼電器、Motor

(七)、鎖存器1、原理藍橋杯中數據傳入口都是P0&#xff0c;也就是數碼管段選、位選數據、LED亮滅的數據、蜂鳴器啟動或禁用的數據&#xff0c;外設啟動或者關閉都需要通過P0寫入數據&#xff0c;那么如何這樣共用一個端口會造成沖突嘛&#xff0c;答案是肯定的。所以藍橋杯加入…

AI熱點周報(8.3~8.9):OpenAI重返開源,Anthropic放大招,Claude4.1、GPT5相繼發布

名人說&#xff1a;博觀而約取&#xff0c;厚積而薄發。——蘇軾《稼說送張琥》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 目錄一、OpenAI的"開源回歸"&#xff1a;時隔5年的戰略大轉彎1. GPT-OSS系列&a…

《Kubernetes部署篇:基于x86_64+aarch64架構CPU+containerd一鍵離線部署容器版K8S1.33.3高可用集群》

總結&#xff1a;整理不易&#xff0c;如果對你有幫助&#xff0c;可否點贊關注一下&#xff1f; 更多詳細內容請參考&#xff1a;企業級K8s集群運維實戰 一、部署背景 由于業務系統的特殊性&#xff0c;我們需要針對不同的客戶環境部署基于containerd容器版 K8S 1.33.3集群&a…

Linux抓包命令tcpdump詳解筆記

文章目錄一、tcpdump 是什么&#xff1f;二、基本語法三、常用參數說明四、抓包示例&#xff08;通俗易懂&#xff09;1. 抓所有數據包&#xff08;默認 eth0&#xff09;2. 指定接口抓包3. 抓取端口 80 的數據包&#xff08;即 HTTP 請求&#xff09;4. 抓取訪問某個 IP 的數據…

抖音、快手、視頻號等多平臺視頻解析下載 + 磁力嗅探下載、視頻加工(提取音頻 / 壓縮等)

跟你們說個安卓上的下載工具&#xff0c;還挺厲害的。它能支持好多種下載方式&#xff0c;具體多少種我沒細數&#xff0c;反正挺全乎的。? 平時用得最多的就是視頻解析&#xff0c;像抖音、快手、B 站上那些視頻&#xff0c;想存下來直接用它就行&#xff0c;連海外視頻的也能…