国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向

這篇具有很好參考價(jià)值的文章主要介紹了【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

??作者:阿潤(rùn)菜菜
??專欄:Linux系統(tǒng)編程



重新認(rèn)識(shí)文件

  1. 是不是只有C/C++有文件操作呢?python、java、go等文件接口操作的方法是不太一樣的,那如何理解這種現(xiàn)象?有沒有統(tǒng)一的視角去看待所有的語(yǔ)言文件操作呢?—我們今天從系統(tǒng)視角去理解 ---- 實(shí)際都是通過系統(tǒng)調(diào)用來訪問
  2. 文件=內(nèi)容+屬性 — 針對(duì)文件的操作:對(duì)內(nèi)容的操作,對(duì)屬性的操作,對(duì)內(nèi)容和屬性的操作
  3. 文件可以分為兩大類:磁盤文件 和 被打開的文件(內(nèi)存文件)
  4. 當(dāng)文件沒有被操作的時(shí)候,文件一般放在磁盤位置??瘴募苍诖疟P中占據(jù)空間,因?yàn)槲募傩砸彩菙?shù)據(jù),保存數(shù)據(jù)就需要空間。
  5. 我們?cè)谖募僮鞯臅r(shí)候,文件需要在哪里?—內(nèi)存,依據(jù)馮諾依曼體系的規(guī)定
  6. 所以我們?cè)谖募僮鞯臅r(shí)候,文件需要提前l(fā)oad到內(nèi)存,那load是內(nèi)容還是屬性?至少有屬性吧!那是不是只有你一個(gè)人在load呢?當(dāng)然不是,內(nèi)存中一定存在大量的不同文件的屬性
  7. 所以,打開文件的本質(zhì)就是將需要的文件加載到內(nèi)存中,OS內(nèi)部一定會(huì)同時(shí)存在大量的被打開的文件,那操作系統(tǒng)需不需要管理呢?怎么管理?— 先描述,在組織!
  8. 先描述 — 構(gòu)建在內(nèi)存中的文件結(jié)構(gòu)體 struct file (文件從磁盤中來,struct file* next連接下一個(gè)文件信息)。在組織 — struct file結(jié)構(gòu)體利用某種數(shù)據(jù)結(jié)構(gòu)鏈接起來。在OS內(nèi)部,對(duì)被打開的文件進(jìn)行管理,就轉(zhuǎn)換成了對(duì)類似鏈表的增刪查改
  9. 結(jié)論:文件被打開,OS要為被打開的文件,創(chuàng)建對(duì)應(yīng)的內(nèi)核數(shù)據(jù)結(jié)構(gòu)
  10. 所有文件操作的本質(zhì)就是進(jìn)程和被打開文件的關(guān)系。 — struct task_struct 和 struct file

系統(tǒng)內(nèi)部的文件操作

庫(kù)函數(shù)底層必須調(diào)用系統(tǒng)調(diào)用接口,因?yàn)闊o(wú)論什么進(jìn)程想訪問文件,都必須按照操作系統(tǒng)提供的方式來進(jìn)行訪問,所以就算文件操作相關(guān)函數(shù)千變?nèi)f化,但是底層是不變的,這些函數(shù)最后都會(huì)調(diào)用系統(tǒng)調(diào)用接口,按照操作系統(tǒng)的意愿來合理的訪問磁盤上的文件。

我們不能用語(yǔ)言繞過操作系統(tǒng)去操縱硬件,所以必須通過系統(tǒng)調(diào)用通過操作系統(tǒng)來進(jìn)行文件操作!不管什么編程語(yǔ)言,只是不同語(yǔ)言對(duì)系統(tǒng)調(diào)用進(jìn)行了各自不同的封裝,所以對(duì)這些文件操作接口的理解,其實(shí)就要落實(shí)到對(duì)系統(tǒng)調(diào)用接口的理解! 也就是說所有的只要要訪問硬件或者操作系統(tǒng)內(nèi)部的資源,都要通過系統(tǒng)調(diào)用!避不開的!

我們C語(yǔ)言的文件操作

C語(yǔ)言文件操作接口主要包括以下幾類:

  • 打開和關(guān)閉文件的接口,如fopen(), fclose()等。這些接口用于創(chuàng)建或打開一個(gè)文件,并返回一個(gè)FILE類型的指針,以及關(guān)閉一個(gè)已打開的文件,并釋放相關(guān)資源。
  • 順序讀寫數(shù)據(jù)的接口,如fgetc(), fputc(), fgets(), fputs(), fprintf(), fscanf()等。這些接口用于從文件中讀取或?qū)懭胱址?、字符串或格式化?shù)據(jù),并自動(dòng)移動(dòng)文件指針。
  • 隨機(jī)讀寫數(shù)據(jù)的接口,如fread(), fwrite(), fseek(), ftell()等。這些接口用于從文件中讀取或?qū)懭攵M(jìn)制數(shù)據(jù)塊,并根據(jù)指定位置移動(dòng)或獲取文件指針。
  • 其他輔助功能的接口,如feof(), ferror(), clearerr()等。這些接口用于檢測(cè)文件是否到達(dá)末尾、是否發(fā)生錯(cuò)誤、以及清除錯(cuò)誤標(biāo)志。

文件的打開方式:
r:以只讀的方式打開文件,若文件不存在就會(huì)出錯(cuò)。
w:以只寫的方式打開文件,文件若存在則清空文件內(nèi)容重新開始寫入,若不存在則創(chuàng)建一個(gè)文件。
a:以只寫的方式打開文件,文件若存在則從文件尾部以追加的方式進(jìn)行寫入,若不存在則創(chuàng)建一個(gè)文件。
r+:以可讀寫的方式打開文件,若文件不存在就會(huì)出錯(cuò)。
w+:以可讀寫的方式打開文件,其他與w一樣。
a+:以可讀寫的方式打開文件,其他與a一樣。

fopen, fread, fwrite, fseek, fclose等函數(shù)的使用

需要注意的是,當(dāng)向文件中寫入數(shù)據(jù)后,想要重新讀取到數(shù)據(jù),要么需要關(guān)閉文件重新打開,要么就要跳轉(zhuǎn)讀寫位置到文件起始位置,然后再開始讀取文件數(shù)據(jù)。

#include <stdio.h>
#include <string.h>
 
 
int main()
{
    FILE *fp = fopen("./bite", "wb+");
    if (fp == NULL) {
        perror("fopen error");
        return -1; 
    }   
    fseek(fp, 0, SEEK_SET);
    char *data = "linux so easy!\n";
    //size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    size_t ret = fwrite(data, 1, strlen(data), fp);
    if (ret != strlen(data)) {
        perror("fwrite error");
        return -1; 
    }   
    fseek(fp, 0, SEEK_SET);//跳轉(zhuǎn)讀寫位置到,從文件起始位置開始偏移0個(gè)字節(jié)
    char buf[1024] = {0};
    //size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    ret = fread(buf, 1, 1023, fp);//因?yàn)樵O(shè)置讀取塊大小位1,塊個(gè)數(shù)為1023因此fread返回值為實(shí)際讀取到的數(shù)據(jù)長(zhǎng)度
    if (ret == 0) {
        if (ferror(fp)) //判斷上一次IO操作是否正確
            printf("fread error\n");
        if (feof(fp)) //判斷是否讀取到了文件末尾
            printf("read end of file!\n");
        return -1; 
    }   
    printf("%s", buf);
    fclose(fp);
    return 0;
}

當(dāng)然這些也都是C庫(kù)提供的函數(shù),是對(duì)系統(tǒng)調(diào)用的上層封裝,在系統(tǒng)級(jí)別文件操作我們是通過系統(tǒng)調(diào)用實(shí)現(xiàn)的

系統(tǒng)內(nèi)部的文件操作

文件操作系統(tǒng)調(diào)用接口是指Linux內(nèi)核提供的一組用于對(duì)文件進(jìn)行打開、讀寫、關(guān)閉等操作的函數(shù)。它們包括以下幾個(gè)常用的函數(shù):

  • open:打開一個(gè)文件,返回一個(gè)文件描述符,可以指定文件的打開方式和權(quán)限。
  • write:向一個(gè)已打開的文件中寫入數(shù)據(jù),返回實(shí)際寫入的字節(jié)數(shù)。
  • read:從一個(gè)已打開的文件中讀取數(shù)據(jù),返回實(shí)際讀取的字節(jié)數(shù)。
  • lseek:改變一個(gè)已打開文件的讀寫位置,返回新的偏移量。
  • close:關(guān)閉一個(gè)已打開的文件,釋放資源。

這些函數(shù)都需要傳入一個(gè)文件描述符作為參數(shù),它是一個(gè)非負(fù)整數(shù),用于標(biāo)識(shí)不同的打開文件。每個(gè)進(jìn)程都有自己獨(dú)立的一組文件描述符,并且默認(rèn)有三個(gè)預(yù)定義的描述符:0代表標(biāo)準(zhǔn)輸入,1代表標(biāo)準(zhǔn)輸出,2代表標(biāo)準(zhǔn)錯(cuò)誤輸出。

這些函數(shù)都有可能失敗,并返回-1,并設(shè)置errno變量為相應(yīng)的錯(cuò)誤碼。因此,在調(diào)用這些函數(shù)后,需要檢查返回值和錯(cuò)誤碼來判斷是否成功。
我們主要介紹前三個(gè):

OS一般會(huì)如何讓用戶給自己傳遞標(biāo)志位的?多個(gè)標(biāo)志位怎么實(shí)現(xiàn)呢? — 位圖

其實(shí)是通過位操作實(shí)現(xiàn)的:

#include <stdio.h>

#define ONE 0x1
#define TWO 0x2
#define THREE 0x4
#define FOUR 0x8
#define FIVE 0x10

// 0000 0000 0000 0000 0000 0000 0000 0000
void Print(int flags)
{
    if(flags & ONE) printf("hello 1\n"); //充當(dāng)不同的行為
    if(flags & TWO) printf("hello 2\n");
    if(flags & THREE) printf("hello 3\n");
    if(flags & FOUR) printf("hello 4\n");
    if(flags & FIVE) printf("hello 5\n");
}


int main()
{
    printf("--------------------------\n");
    Print(ONE);
    printf("--------------------------\n");
    Print(TWO);
    printf("--------------------------\n");
    Print(FOUR);
    printf("--------------------------\n");

    Print(ONE|TWO);
    printf("--------------------------\n");

    Print(ONE|TWO|THREE);
    printf("--------------------------\n");

    Print(ONE|TWO|THREE|FOUR|FIVE);
    printf("--------------------------\n");

    return 0;
}

open:打開一個(gè)文件,返回一個(gè)文件描述符,可以指定文件的打開方式和權(quán)限

open有兩種調(diào)用方式:
一種是只傳入文件名和訪問模式,另一種是還傳入創(chuàng)建權(quán)限(如果需要?jiǎng)?chuàng)建新文件)。訪問模式有必需部分和可選部分,必需部分是 O_RDONLY(只讀)、O_WRONLY(只寫)或 O_RDWR(讀寫),可選部分有 O_APPEND(追加)、O_TRUNC(截?cái)啵_CREAT(創(chuàng)建)、O_EXCL(排他)等。創(chuàng)建權(quán)限是由幾個(gè)標(biāo)志按位或得到的,如 S_IRUSR(用戶讀)、S_IWUSR(用戶寫)、S_IXUSR(用戶執(zhí)行)等。

字符串/0 問題: 系統(tǒng)調(diào)用不需要這個(gè)!【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO

【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO

使用 open 函數(shù)打開一個(gè)文件,如果不存在則創(chuàng)建一個(gè)新文件,并設(shè)置訪問模式為讀寫和追加,創(chuàng)建權(quán)限為用戶讀寫和組讀寫:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>

int main() {
    // 打開或創(chuàng)建一個(gè)文件
    int fd = open("test.txt", O_RDWR | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    if (fd == -1) {
        // 打開失敗,打印錯(cuò)誤信息
        perror("open error");
        exit(1);
    }
    // 打開成功,打印文件描述符
    printf("open success, fd = %d\n", fd);
    // 關(guān)閉文件
    close(fd);
    return 0;
}

創(chuàng)建目錄的命令mkdir,目錄起始權(quán)限默認(rèn)是0777,創(chuàng)建文件的命令touch,文件起始權(quán)限是0666,這些命令的實(shí)現(xiàn)實(shí)際上是要調(diào)用系統(tǒng)接口open的,并且在創(chuàng)建文件或目錄的時(shí)候要在open的第三個(gè)參數(shù)中設(shè)置文件的起始權(quán)限。

 25 int main()
 26 {
 27     umask(0);//將進(jìn)程的umask值設(shè)置為0000
 28 
 29     // C語(yǔ)言中的w選項(xiàng)實(shí)際上底層需要調(diào)用這么多的選項(xiàng)O_WRONLY O_CREAT O_TRUNC 0666
 30     // C語(yǔ)言中的a選項(xiàng)需要將O_TRUNC替換為O_APPEND
 31     int fd = open(FILE_NAME,O_WRONLY | O_CREAT,0666);//設(shè)置文件起始權(quán)限為0666
 32     if(fd < 0)
 33     {
 34         perror("open");
 35         return 1;//退出碼設(shè)置為1
 36     }
 37     close(fd);   
 38 }

### write:向一個(gè)已打開的文件中寫入數(shù)據(jù),返回實(shí)際寫入的字節(jié)數(shù)
**write:向一個(gè)已打開的文件中寫入數(shù)據(jù),返回實(shí)際寫入的字節(jié)數(shù)。需要傳入文件描述符、數(shù)據(jù)緩沖區(qū)和數(shù)據(jù)長(zhǎng)度。如果返回值小于請(qǐng)求的字節(jié)數(shù),可能是因?yàn)殄e(cuò)誤或者設(shè)備驅(qū)動(dòng)程序?qū)?shù)據(jù)塊長(zhǎng)度敏感。如果返回值為 0,表示沒有寫入任何數(shù)據(jù);如果返回值為 -1,則表示出現(xiàn)錯(cuò)誤。**

使用 write 函數(shù)向一個(gè)已打開的文件中寫入一段字符串,并檢查返回值是否正確:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    // 要寫入的字符串和長(zhǎng)度
    char *str = "Hello world!\n";
    int len = 13;
    // 向標(biāo)準(zhǔn)輸出(文件描述符為1)寫入字符串
    int ret = write(1, str, len);
    if (ret == -1) {
        // 寫入失敗,打印錯(cuò)誤信息
        perror("write error");
        exit(1);
    }
    if (ret != len) {
        // 寫入字節(jié)數(shù)不正確,打印警告信息
        fprintf(stderr, "write warning: expected %d bytes, but got %d bytes\n", len, ret);
    }
    // 寫入成功,打印返回值
    printf("write success, ret = %d\n", ret);
    
}

read:從一個(gè)已打開的文件中讀取數(shù)據(jù),返回實(shí)際讀取的字節(jié)數(shù)

read:從一個(gè)已打開的文件中讀取數(shù)據(jù),返回實(shí)際讀取的字節(jié)數(shù)。需要傳入文件描述符、數(shù)據(jù)緩沖區(qū)和數(shù)據(jù)長(zhǎng)度。如果返回值小于請(qǐng)求的字節(jié)數(shù),可能是因?yàn)殄e(cuò)誤或者已到達(dá)文件尾。如果返回值為 0,表示沒有讀取任何數(shù)據(jù);如果返回值為 -1,則表示出現(xiàn)錯(cuò)誤。
使用 read 函數(shù)從一個(gè)已打開的文件中讀取一定長(zhǎng)度的數(shù)據(jù),并存儲(chǔ)到一個(gè)緩沖區(qū)中,并檢查返回值是否正確:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
   // 要讀取的字節(jié)數(shù)和緩沖區(qū)大小 
   int len = 100;
   char buf[100];
   // 從標(biāo)準(zhǔn)輸入(文件描述符為0)讀取數(shù)據(jù)到緩沖區(qū)中
   int ret = read(0, buf, len);
   if (ret == -1) {
       // 讀取失敗,打印錯(cuò)誤信息
       perror("read error");
       exit(1);
   }
   if (ret == 0) {
       // 讀取到文件尾,沒有數(shù)據(jù)可讀,打印提示信息
       printf("read end of file\n");
   }
   // 讀取成功,打印返回值和緩沖區(qū)內(nèi)容(注意添加結(jié)束符)
   printf("read success, ret = %d\n", ret);
  buf[ret] = '\0';
   printf("buf: %s\n", buf);

}

使用這些接口時(shí),有一些事項(xiàng)需要注意:

  • 在調(diào)用 open 函數(shù)時(shí),要根據(jù)文件的用途和狀態(tài)選擇合適的訪問模式和創(chuàng)建權(quán)限。如果使用了 O_CREAT 標(biāo)志,要指定創(chuàng)建權(quán)限,否則可能導(dǎo)致文件權(quán)限不正確。如果使用了 O_EXCL 標(biāo)志,要檢查返回值是否為 -1,否則可能導(dǎo)致覆蓋已有文件。如果打開的是設(shè)備文件或符號(hào)鏈接,要注意一些特殊的訪問模式,如 O_NONBLOCK、O_NOCTTY、O_NOFOLLOW 等。
  • 在調(diào)用 write 函數(shù)時(shí),要保證數(shù)據(jù)緩沖區(qū)的有效性和長(zhǎng)度正確性。如果寫入的是文本文件,要注意添加換行符或結(jié)束符。如果寫入的是二進(jìn)制文件,要注意字節(jié)序和對(duì)齊問題。如果寫入的是設(shè)備文件或網(wǎng)絡(luò)套接字,要注意數(shù)據(jù)塊長(zhǎng)度和超時(shí)問題。
  • 在調(diào)用 read 函數(shù)時(shí),要保證數(shù)據(jù)緩沖區(qū)的有效性和大小足夠。如果讀取的是文本文件,要注意處理?yè)Q行符或結(jié)束符。如果讀取的是二進(jìn)制文件,要注意字節(jié)序和對(duì)齊問題。如果讀取的是設(shè)備文件或網(wǎng)絡(luò)套接字,要注意數(shù)據(jù)塊長(zhǎng)度和超時(shí)問題。
  • 在調(diào)用這些接口后,都要檢查返回值是否為 -1,并根據(jù) errno 變量來判斷錯(cuò)誤原因,并進(jìn)行相應(yīng)的處理或提示。有些錯(cuò)誤可能是暫時(shí)性的或可恢復(fù)的,如 EINTR、EAGAIN、EWOULDBLOCK 等;有些錯(cuò)誤可能是嚴(yán)重性的或不可恢復(fù)的,如 EACCES、EBADF、EFAULT、EINVAL 等。

綜合使用:
fopen, fread, fwrite, fseek, fclose等函數(shù)的使用
需要注意的是,當(dāng)向文件中寫入數(shù)據(jù)后,想要重新讀取到數(shù)據(jù),要么需要關(guān)閉文件重新打開,要么就要跳轉(zhuǎn)讀寫位置到文件起始位置,然后再開始讀取文件數(shù)據(jù)。

#include <stdio.h>
#include <string.h>
 
 
int main()
{
    FILE *fp = fopen("./bite", "wb+");
    if (fp == NULL) {
        perror("fopen error");
        return -1; 
    }   
    fseek(fp, 0, SEEK_SET);
    char *data = "linux so easy!\n";
    //size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    size_t ret = fwrite(data, 1, strlen(data), fp);
    if (ret != strlen(data)) {
        perror("fwrite error");
        return -1; 
    }   
    fseek(fp, 0, SEEK_SET);//跳轉(zhuǎn)讀寫位置到,從文件起始位置開始偏移0個(gè)字節(jié)
    char buf[1024] = {0};
    //size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    ret = fread(buf, 1, 1023, fp);//因?yàn)樵O(shè)置讀取塊大小位1,塊個(gè)數(shù)為1023因此fread返回值為實(shí)際讀取到的數(shù)據(jù)長(zhǎng)度
    if (ret == 0) {
        if (ferror(fp)) //判斷上一次IO操作是否正確
            printf("fread error\n");
        if (feof(fp)) //判斷是否讀取到了文件末尾
            printf("read end of file!\n");
        return -1; 
    }   
    printf("%s", buf);
    fclose(fp);
    return 0;
}

綜合使用:
open, read, write, lseek, close等函數(shù)的使用

#include <stdio.h>
#include <unistd.h>//是close, write這些接口的頭文件
#include <string.h>
#include <fcntl.h>//是 O_CREAT 這些宏的頭文件
#include <sys/stat.h>//umask接口頭文件
 
 
int main()
{
    //將當(dāng)前進(jìn)程的默認(rèn)文件創(chuàng)建權(quán)限掩碼設(shè)置為0--- 并不影響系統(tǒng)的掩碼,僅在當(dāng)前進(jìn)程內(nèi)生效
    umask(0);
    //int open(const char *pathname, int flags, mode_t mode);
    int fd = open("./bite", O_CREAT|O_RDWR, 0664);
    if(fd < 0) {
        perror("open error");
        return -1; 
    }   
    char *data = "i like linux!\n";
    //ssize_t write(int fd, const void *buf, size_t count);
    ssize_t ret = write(fd, data, strlen(data));
    if (ret < 0) {
        perror("write error");
        return -1; 
    }   
    //off_t lseek(int fd, off_t offset, int whence);
    lseek(fd, 0, SEEK_SET);
    char buf[1024] = {0};
    //ssize_t read(int fd, void *buf, size_t count);
    ret = read(fd, buf, 1023);
    if (ret < 0) {
        perror("read error");
        return -1; 
    }else if (ret == 0) {
        printf("end of file!\n");
        return -1; 
    }   
    printf("%s", buf);
    close(fd);
    return 0;
}

看看Linux內(nèi)核源代碼是怎么說的

【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO
可以看到內(nèi)核源代碼的設(shè)計(jì)內(nèi)容跟我們所說的基本一致

理解文件控制塊&&文件描述符&&文件指針的關(guān)系

在進(jìn)程中每打開一個(gè)文件,都會(huì)創(chuàng)建有相應(yīng)的文件描述信息struct file,這個(gè)描述信息被添加在pcb的struct files_struct中,以數(shù)組的形式進(jìn)行管理,隨即向用戶返回?cái)?shù)組的下標(biāo)作為文件描述符,用于操作文件

進(jìn)程可以打開多個(gè)文件,對(duì)于大量的被打開文件,操作系統(tǒng)一定是要進(jìn)行管理的,也就是先描述再組織,所以操作系統(tǒng)會(huì)為被打開的文件創(chuàng)建對(duì)應(yīng)的內(nèi)核數(shù)據(jù)結(jié)構(gòu),也就是文件控制塊FCB,在linux源碼中是struct file{}結(jié)構(gòu)體,包含了文件的大部分屬性

 #include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define FILE_NAME(number) "log.txt"#number

int main()
{
    int fd0 = open(FILE_NAME(1),O_WRONLY | O_CREAT | O_TRUNC,0666);//設(shè)置文件起始權(quán)限為0666
    int fd1 = open(FILE_NAME(2),O_WRONLY | O_CREAT | O_TRUNC,0666);//設(shè)置文件起始權(quán)限為0666
    int fd2 = open(FILE_NAME(3),O_WRONLY | O_CREAT | O_TRUNC,0666);//設(shè)置文件起始權(quán)限為0666
    int fd3 = open(FILE_NAME(4),O_WRONLY | O_CREAT | O_TRUNC,0666);//設(shè)置文件起始權(quán)限為0666
    int fd4 = open(FILE_NAME(5),O_WRONLY | O_CREAT | O_TRUNC,0666);//設(shè)置文件起始權(quán)限為0666
    printf("fd:%d\n",fd0);
    printf("fd:%d\n",fd1);
    printf("fd:%d\n",fd2);
    printf("fd:%d\n",fd3);
    printf("fd:%d\n",fd4);
    close(fd0);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);  
}

結(jié)果:
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO
通過上述講解,我們知道open系統(tǒng)調(diào)用會(huì)返回文件描述符,那它為什么是從3開始呢??

其實(shí)main函數(shù)會(huì)默認(rèn)打開這三個(gè)標(biāo)準(zhǔn)文件
這三個(gè)標(biāo)準(zhǔn)文件是:

  • 標(biāo)準(zhǔn)輸入(stdin):用于從鍵盤或其他輸入設(shè)備讀取數(shù)據(jù),通常對(duì)應(yīng)文件描述符0。可以使用C語(yǔ)言的scanf、getchar等函數(shù)或者Linux的read系統(tǒng)調(diào)用來讀取標(biāo)準(zhǔn)輸入。
  • 標(biāo)準(zhǔn)輸出(stdout):用于向屏幕或其他輸出設(shè)備寫入數(shù)據(jù),通常對(duì)應(yīng)文件描述符1??梢允褂肅語(yǔ)言的printf、putchar等函數(shù)或者Linux的write系統(tǒng)調(diào)用來寫入標(biāo)準(zhǔn)輸出。
  • 標(biāo)準(zhǔn)錯(cuò)誤輸出(stderr):用于向屏幕或其他輸出設(shè)備寫入錯(cuò)誤信息,通常對(duì)應(yīng)文件描述符2??梢允褂肅語(yǔ)言的fprintf、perror等函數(shù)或者Linux的write系統(tǒng)調(diào)用來寫入標(biāo)準(zhǔn)錯(cuò)誤輸出。

這三個(gè)標(biāo)準(zhǔn)文件在程序啟動(dòng)時(shí)就被自動(dòng)打開,并且在程序結(jié)束時(shí)被自動(dòng)關(guān)閉,無(wú)需手動(dòng)操作。它們也可以被重定向到其他文件或設(shè)備,例如使用 > 或 < 符號(hào)。
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO

所以為什么open文件操作后返回值 是3? 因?yàn)?0 1 2 已經(jīng)被占用了 ---- 本質(zhì)是數(shù)組下標(biāo)

內(nèi)存中文件描述符,文件描述符表,文件控制塊,進(jìn)程控制塊的關(guān)系如下圖所示,文件描述符表,說白了就是一個(gè)存儲(chǔ)指向文件控制塊的指針的指針數(shù)組,而文件描述符就是這個(gè)指針數(shù)組的索引,進(jìn)程控制塊中會(huì)有一個(gè)指向文件描述符表的指針。通過文件描述符就可以找到對(duì)應(yīng)的被打開的文件。
操作系統(tǒng)通過這些內(nèi)核數(shù)據(jù)結(jié)構(gòu),將被打開的文件和進(jìn)程聯(lián)系起來。

【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO

深度理解

文件描述符的實(shí)質(zhì):文件描述符是內(nèi)核為每個(gè)進(jìn)程維護(hù)的一個(gè)打開文件記錄表的索引值

C語(yǔ)言如何訪問系統(tǒng)? 就是通過文件描述符;同樣的C++的cin、cout等類中也必須有文件描述符!沒有文件描述符,怎么通過操作系統(tǒng)訪問(系統(tǒng)調(diào)用)外設(shè)呢! 每個(gè)編程語(yǔ)言都是如此!
通過上述的引出,我們可以知道文件描述符的實(shí)質(zhì)是:

  • 文件描述符是一個(gè)非負(fù)整數(shù),用于標(biāo)識(shí)不同的已打開文件。
  • 文件描述符是內(nèi)核為了高效管理已打開文件所創(chuàng)建的索引,它可以用來調(diào)用各種I/O系統(tǒng)調(diào)用函數(shù)。
  • 文件描述符是進(jìn)程級(jí)別的,每個(gè)進(jìn)程都有自己獨(dú)立的一組文件描述符,并且默認(rèn)有三個(gè)預(yù)定義的描述符:0代表標(biāo)準(zhǔn)輸入,1代表標(biāo)準(zhǔn)輸出,2代表標(biāo)準(zhǔn)錯(cuò)誤輸出
  • 文件描述符可以被復(fù)制、重定向、關(guān)閉等操作,但不能被直接讀寫。要讀寫一個(gè)已打開文件,需要使用read、write等系統(tǒng)調(diào)用函數(shù),并傳入相應(yīng)的文件描述符作為參數(shù)。

文件描述符表和file結(jié)構(gòu)體之間的關(guān)系是:

  • 文件描述符表是內(nèi)核用來存儲(chǔ)每個(gè)進(jìn)程的文件描述符和對(duì)應(yīng)的打開文件信息的表格。每個(gè)進(jìn)程在其進(jìn)程控制塊(PCB)中都保存著一份文件描述符表
  • file結(jié)構(gòu)體是內(nèi)核用來表示已打開文件的數(shù)據(jù)結(jié)構(gòu),它包含了當(dāng)前讀寫位置、訪問模式、狀態(tài)標(biāo)志等信息,以及指向?qū)?yīng)inode對(duì)象或者i-node表項(xiàng)的指針。file結(jié)構(gòu)體也可以稱為打開文件句柄或者打開文件表項(xiàng)。
  • 文件描述符表和file結(jié)構(gòu)體之間通過指針相互連接,一個(gè)文件描述符可以指向一個(gè)或多個(gè)file結(jié)構(gòu)體,一個(gè)file結(jié)構(gòu)體也可以被一個(gè)或多個(gè)文件描述符所指向。這樣可以實(shí)現(xiàn)不同進(jìn)程或同一進(jìn)程中不同文件描述符共享同一個(gè)已打開文件。

文件描述符的分配規(guī)則:系統(tǒng)在創(chuàng)建文件描述符時(shí)會(huì)尋找當(dāng)前未使用的最小下標(biāo)

關(guān)閉012文件描述符產(chǎn)生的現(xiàn)象(新打開文件的fd被賦值為0或1或2)

當(dāng)關(guān)閉0或2時(shí),打印出來的log.txt對(duì)應(yīng)的fd的值就是對(duì)應(yīng)的關(guān)閉的0或2的值,而當(dāng)關(guān)閉1時(shí),顯示器不會(huì)顯示對(duì)應(yīng)的fd的值。

  1 #include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 
  7 int main()
  8 {
  9     //close(0);
 10     //close(1);
 11     //close(2);                                                                                                                                        
 12     umask(0000);                                                                                                             
 13     int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);//沒有指明文件路徑,默認(rèn)在當(dāng)前路徑下,也就是當(dāng)前進(jìn)程的工作目錄
 14     if(fd<0)                                                   
 15     {                                                          
 16         perror("open");                                        
 17         return 1;                                              
 18     }                                                          
 19                                                                
 20     printf("open fd:%d\n",fd);                                 
 21     close(fd);                                                 
 22     return 0;                                                  
 23 }    

測(cè)試結(jié)果:
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO
分析:
所以實(shí)際上文件描述符在分配時(shí),會(huì)從文件描述符表中的指針數(shù)組中,從小到大按照順序找最小的且沒有被占用的fd來進(jìn)行分配,自然而然關(guān)閉0時(shí),0對(duì)應(yīng)存儲(chǔ)的地址就會(huì)由stdin改為新打開的文件的地址,所以打印新的文件的fd值時(shí),就會(huì)出現(xiàn)0。
關(guān)閉2也是這個(gè)道理,fd為2對(duì)應(yīng)的存儲(chǔ)的地址會(huì)由stderr改為新打開的文件的地址,所以在打印fd時(shí),也就會(huì)出現(xiàn)2了。

文件描述符的分配規(guī)則是:

  • 當(dāng)一個(gè)進(jìn)程打開一個(gè)新的文件時(shí),系統(tǒng)會(huì)在該進(jìn)程的文件描述符表中尋找當(dāng)前未使用的最小下標(biāo),并將其分配給該文件。
  • 當(dāng)一個(gè)進(jìn)程關(guān)閉一個(gè)已打開的文件時(shí),系統(tǒng)會(huì)將該文件對(duì)應(yīng)的文件描述符表項(xiàng)置為空,并釋放其占用的資源。
  • 當(dāng)一個(gè)進(jìn)程復(fù)制或重定向一個(gè)已打開的文件時(shí),系統(tǒng)會(huì)在該進(jìn)程或目標(biāo)進(jìn)程的文件描述符表中尋找當(dāng)前未使用的最小下標(biāo),并將其指向同一個(gè)file結(jié)構(gòu)體。

下面是一些示例代碼:

  • 打開一個(gè)新的文件:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>

int main() {
    // 打開或創(chuàng)建一個(gè)新文件
    int fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd == -1) {
        // 打開失敗,打印錯(cuò)誤信息并退出
        perror("open error");
        exit(1);
    }
    // 打開成功,打印分配到的文檔描述符
    printf("open success, fd = %d\n", fd);
    // 關(guān)閉文檔
    close(fd);
    return 0;
}
  • 關(guān)閉一個(gè)已打開的文檔:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>

int main() {
    // 打開或創(chuàng)建一個(gè)新文檔
    int fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd == -1) {
        // 打開失敗,打印錯(cuò)誤信息并退出
        perror("open error");
        exit(1);
    }
    // 打開成功,打印分配到的文檔描述符
    printf("open success, fd = %d\n", fd);
    
    // 關(guān)閉文檔
    int ret = close(fd);
    
     if (ret == -1) {
        // 關(guān)閉失敗,打印錯(cuò)誤信息并退出
        perror("close error");
        exit(1);
     }
     // 關(guān)閉成功,打印關(guān)閉信息
     printf("close success\n");
     
     return 0;
}

文件重定向與dup2系統(tǒng)調(diào)用 (內(nèi)核中更改fd對(duì)應(yīng)的struct file*地址)

重定向命令>和>>的含義和用法

  • 重定向命令>和>>都是用來將一個(gè)命令的標(biāo)準(zhǔn)輸出或錯(cuò)誤輸出重定向到一個(gè)文件中,而不是顯示在屏幕上。
  • 重定向命令>表示覆蓋模式,即如果目標(biāo)文件已經(jīng)存在,那么原來的內(nèi)容會(huì)被清空,然后寫入新的內(nèi)容。例如:echo “hello” > log.txt 表示將字符串"hello"寫入到log.txt文件中,如果log.txt文件已經(jīng)存在,那么原來的內(nèi)容會(huì)被覆蓋。
  • 重定向命令>>表示追加模式,即如果目標(biāo)文件已經(jīng)存在,那么新的內(nèi)容會(huì)被追加到原來的內(nèi)容后面。例如:echo “world” >> log.txt 表示將字符串"world"追加到log.txt文件中,如果log.txt文件已經(jīng)存在,那么原來的內(nèi)容會(huì)保留。
  • 重定向命令>和>>可以指定不同的文件描述符來重定向不同類型的輸出。默認(rèn)情況下,如果不指定文件描述符,那么就是1,表示標(biāo)準(zhǔn)輸出。如果要重定向錯(cuò)誤輸出,就要指定2作為文件描述符。例如:ls -l /etc/passwd /etc/abc > log1.txt 2> log2.txt 表示將ls -l 命令的標(biāo)準(zhǔn)輸出重定向到log1.txt文件中,并將錯(cuò)誤輸出重定向到log2.txt文件中。
    測(cè)試如下:

我們vim一個(gè)abc文件,可以看到abc文件中的內(nèi)容如下圖所示:
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO

然后我們使用 ls > abc 命令之后可以看到abc中的內(nèi)容已經(jīng)被清空重定向了
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO

:追加重定向,直接在文件的尾部進(jìn)行重定向

我們對(duì)abc文件進(jìn)行追加重定向,可以看到,直接在文件的尾巴進(jìn)行了重定向
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO

重定向原理

簡(jiǎn)單說將 fd_array 數(shù)組當(dāng)中的元素struct file* 指針的指向關(guān)系進(jìn)行修改,改變成為其它的struct file結(jié)構(gòu)體的地址—每個(gè)文件描述符都是一個(gè)內(nèi)核中文件描述信息數(shù)組的下標(biāo),對(duì)應(yīng)有一個(gè)文件的描述信息用于操作文件,而重定向就是在不改變所操作的文件描述符的情況下,通過改變描述符對(duì)應(yīng)的文件描述信息進(jìn)而實(shí)現(xiàn)改變所操作的文件

詳細(xì)說文件操作重定向的原理是通過改變文件描述符對(duì)應(yīng)的文件描述信息,從而實(shí)現(xiàn)改變所操作的文件。文件描述符是一個(gè)整數(shù),表示進(jìn)程和被打開文件的關(guān)系,通常有標(biāo)準(zhǔn)輸入(0)、標(biāo)準(zhǔn)輸出(1)和標(biāo)準(zhǔn)錯(cuò)誤(2)三種。重定向可以分為輸出重定向、追加重定向和輸入重定向三種類型。輸出重定向是將本應(yīng)該打印到顯示器的內(nèi)容輸出到了指定的文件中,例如 ls > list.txt;追加重定向是將本應(yīng)該打印到顯示器的內(nèi)容追加式地輸出到了指定的文件中,例如 ls >> list.txt;輸入重定向是將本應(yīng)該從鍵盤中讀取的內(nèi)容改為從指定的文件中讀取,例如 cat < input.txt。在Linux系統(tǒng)中,可以使用dup2系統(tǒng)調(diào)用來實(shí)現(xiàn)重定向,它可以將一個(gè)文件描述符復(fù)制到另一個(gè)文件描述符,并關(guān)閉后者。
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO

dup2函數(shù)的功能和參數(shù)含義

int dup2(int oldfd, int newfd); 其實(shí)這個(gè)函數(shù)挺繞的,要理解起來需要自己研究一下才行:

通過man手冊(cè)我們可以對(duì)dup2函數(shù)進(jìn)行一些了解:
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO
int dup2(int oldfd, int newfd);
函數(shù)功能為將newfd描述符重定向到oldfd描述符,相當(dāng)于重定向完畢后都是操作oldfd所操作的文件
但是在過程中如果newfd本身已經(jīng)有對(duì)應(yīng)打開的文件信息,則會(huì)先關(guān)閉文件后再重定向(否則會(huì)資源泄露)

怎么用?怎么傳參數(shù)?— 拷貝的整數(shù)所表示的內(nèi)容 — 注意最后只有oldfd保留就可以了?。?/mark> 就是oldfd把newfd覆蓋了 — 一般傳參例如:fd 1 (重定向輸出)— 只保留了fd

所以dup2函數(shù)是一個(gè)用于復(fù)制文件描述符的系統(tǒng)調(diào)用,它的功能是將參數(shù)oldfd所指的文件描述符復(fù)制到參數(shù)newfd所指定的數(shù)值,如果newfd已經(jīng)被打開,則先關(guān)閉它,如果newfd等于oldfd,則不做任何操作。dup2函數(shù)返回新的文件描述符,或者在出錯(cuò)時(shí)返回-1。

  1. 輸出重定向:從原來的輸出到屏幕改為輸出到文件中,這就叫做輸出重定向。
    而追加重定向的方式也比較簡(jiǎn)單,只要將文件打開方式中的O_TRUNC替換為O_APPEND即可。
    8 int main()                            
    9 {
   10     umask(0000);                                                           
   11     int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);//輸出重定向
E> 12     int fd = open("log.txt",O_WRONLY | O_CREAT | O_APPEND,0666);//追加重定向
   13     if(fd<0)                                                                                                                                       
   14     {                                                                                  
   15         perror("open");                                                                
   16         return 1;                                                                      
   17     }                                                                                  
   18                                                                                        
   19     dup2(fd,1);                                                                        
   20                                                                                        
   21     printf("open fd:%d\n",fd);// printf --> stdout                                     
   22     fprintf(stdout,"open fd:%d\n",fd);// fprintf --> stdout                            
   23                                                                                        
   24     const char* msg = "hello linux";                                                   
   25     write(1,msg,strlen(msg));//向顯示器上write                                         
   26                                                                                        
   27     close(fd);                                                                         
   28     return 0;                                                                          
   29 }      
  1. 輸出重定向:從原來的鍵盤中讀取數(shù)據(jù),改為從文件fd中讀取數(shù)據(jù),這就叫做輸入重定向。
    文件log.txt中的內(nèi)容,作為輸入重定向重新輸出到顯示器中,即使fgets獲取的方式是stdin也沒有關(guān)系,因?yàn)槲覀兪褂胐up2將stdin中的地址改為了文件log.txt的地址
  8 int main()
  9 {
 10     umask(0000);
 13     int fd = open("log.txt",O_RDONLY);//輸入重定向
 14     if(fd<0)
 15     {
 16         perror("open");
 17         return 1;
 18     }
 19 
 20     dup2(fd,0);//由鍵盤讀取改為從fd文件中讀取                                                                                                        
 21     char line[64];                  
 22     while(1)                                                                                                                  
 23     {                                                                                                                         
 24         printf("<");                                                                                                          
 25         if(fgets(line,sizeof(line),stdin)==NULL) break;                                                                       
 26         printf("%s",line);                                                                                                    
 27     }     
 28 }       

示例:

 void func() {
     int fd = open("./tmp.txt", O_RDWR|O_CREAT, 0664);//打開文件
     if (fd < 0) {
     return -1;
     }
     //將標(biāo)準(zhǔn)輸出,重定向到文件,這樣則寫往標(biāo)準(zhǔn)輸出的數(shù)據(jù)會(huì)被寫入到文件中,而不是被打印
     dup2(fd, 1);
     ?//printf內(nèi)部操作的是stdout標(biāo)準(zhǔn)輸出文件流指針,而文件流指針本質(zhì)上內(nèi)部包含的是1號(hào)描述符成員
     //printf的打印就是向標(biāo)準(zhǔn)輸出寫入數(shù)據(jù),因?yàn)闃?biāo)準(zhǔn)輸出已經(jīng)被重定向,因此數(shù)據(jù)會(huì)被寫入文件中,而不是直接打印
     printf("hello bit");
     return 0;
}

Linux下面一切皆文件!

不同的硬件的讀寫方法一定是不一樣的,但在OS看來,一切設(shè)備和文件都是struct file內(nèi)核數(shù)據(jù)結(jié)構(gòu),在管理對(duì)應(yīng)的硬件時(shí),雖然硬件的管理方法不在OS層,而是在驅(qū)動(dòng)層,這也沒有關(guān)系,只需要利用struct file結(jié)構(gòu)體中的函數(shù)指針,調(diào)用對(duì)應(yīng)的硬件的讀寫方法即可。

終究還是封裝的思想!
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO
Linux下一切皆文件是指,Linux系統(tǒng)中的所有資源,無(wú)論是硬件設(shè)備、普通文件、目錄、進(jìn)程、網(wǎng)絡(luò)連接等,都可以被抽象為文件,并且可以使用統(tǒng)一的接口來訪問和操作。

這樣做的好處是,簡(jiǎn)化了開發(fā)者和用戶對(duì)不同資源的處理方式,提高了系統(tǒng)的靈活性和可擴(kuò)展性。

這樣做的不利之處是,需要在文件系統(tǒng)中掛載每個(gè)硬件設(shè)備才能使用它們,而且可能會(huì)造成一些性能損失。
【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向,Linux系統(tǒng)網(wǎng)絡(luò)編程,linux,運(yùn)維,基礎(chǔ)IO文章來源地址http://www.zghlxwxcb.cn/news/detail-802681.html

到了這里,關(guān)于【Linux】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【探索Linux】—— 強(qiáng)大的命令行工具 P.12(文件描述符 | 重定向 | 基礎(chǔ)IO)

    【探索Linux】—— 強(qiáng)大的命令行工具 P.12(文件描述符 | 重定向 | 基礎(chǔ)IO)

    前面我們講了C語(yǔ)言的基礎(chǔ)知識(shí),也了解了一些數(shù)據(jù)結(jié)構(gòu),并且講了有關(guān)C++的一些知識(shí),也學(xué)習(xí)了一些Linux的基本操作,也了解并學(xué)習(xí)了有關(guān)Linux開發(fā)工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代碼也相信大家都掌握的不錯(cuò),上一篇文章我們了解了基礎(chǔ)IO,文件操作,今天

    2024年02月08日
    瀏覽(30)
  • 【探索Linux】文件描述符 | 重定向 | 基礎(chǔ)IO —— 強(qiáng)大的命令行工具 P.12

    【探索Linux】文件描述符 | 重定向 | 基礎(chǔ)IO —— 強(qiáng)大的命令行工具 P.12

    前面我們講了C語(yǔ)言的基礎(chǔ)知識(shí),也了解了一些數(shù)據(jù)結(jié)構(gòu),并且講了有關(guān)C++的一些知識(shí),也學(xué)習(xí)了一些Linux的基本操作,也了解并學(xué)習(xí)了有關(guān)Linux開發(fā)工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代碼也相信大家都掌握的不錯(cuò),上一篇文章我們了解了基礎(chǔ)IO,文件操作,今天

    2024年02月08日
    瀏覽(25)
  • 【Linux】基礎(chǔ)IO——系統(tǒng)文件IO&&fd&&重定向

    【Linux】基礎(chǔ)IO——系統(tǒng)文件IO&&fd&&重定向

    大家好我是沐曦希?? 空文件,也要在磁盤占據(jù)空間,因?yàn)槲募灿袑傩裕瑢傩砸矊儆跀?shù)據(jù),需要空間進(jìn)行存儲(chǔ)。所以 文件包括內(nèi)容和屬性 所以 對(duì)文件操作就是對(duì)內(nèi)容或者對(duì)屬性進(jìn)行操作,或者對(duì)內(nèi)容和屬性進(jìn)行操作。 文件具有唯一性,所以在 標(biāo)定一個(gè)文件時(shí)候,必須使用

    2024年02月02日
    瀏覽(19)
  • 系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)

    系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫(kù)和靜態(tài)庫(kù)

    C文件接口 C文件接口都是封裝了系統(tǒng)的文件接口,學(xué)習(xí)系統(tǒng)的文件接口有利于更熟悉文件的操作。 open函數(shù) 頭文件 #include sys/types.h #include sys/stat.h #include fcntl.h 函數(shù)描述 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); 參數(shù) pathname: 要打開或創(chuàng)建的目

    2024年02月07日
    瀏覽(21)
  • Linux學(xué)習(xí)之系統(tǒng)默認(rèn)打開的文件描述符、重定向

    Linux學(xué)習(xí)之系統(tǒng)默認(rèn)打開的文件描述符、重定向

    一個(gè)進(jìn)程默認(rèn)會(huì)打開標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、錯(cuò)誤輸出三個(gè)文件描述符??梢栽?/proc/PID/fd 里邊可以看到打開文件的描述符,PID需要改成具體的 pid ,比如可以使用 A終端 輸入 vim proctest 之后按下回車鍵。 打開一個(gè)vim編輯窗口。 再打開一個(gè) B終端 ,輸入 ps -aux | grep \\\'vim\\\' 查找一下

    2024年02月13日
    瀏覽(18)
  • 【Linux】基礎(chǔ) IO(文件描述符)-- 詳解

    【Linux】基礎(chǔ) IO(文件描述符)-- 詳解

    1、 文件的宏觀理解 文件在哪呢? 從廣義上理解,鍵盤、顯示器、網(wǎng)卡、聲卡、顯卡、磁盤等幾乎所有的外設(shè)都可以稱之為文件,因?yàn)?“Linux 下,一切皆文件”。 從狹義上的理解, 文件在 磁盤(硬件) 上放著 ,只有操作系統(tǒng)才能真正的去訪問磁盤。磁盤是一種永久存儲(chǔ)介

    2024年03月24日
    瀏覽(22)
  • 【Linux】文件描述符與重定向操作

    【Linux】文件描述符與重定向操作

    收錄于【Linux】文件系統(tǒng)?專欄 對(duì)于Linux下文件的寫入與讀取,以及文件原理還有疑惑的可以看看上一篇文章淺談文件原理與操作。 目錄 系列文章 再談文件描述符 IO函數(shù)的本質(zhì) 一切皆文件 文件重定向 原理 系統(tǒng)接口 ??上一篇文章中,我們就提到了 open 的返回值即 fd ,又稱

    2024年02月09日
    瀏覽(28)
  • 【Linux】文件的描述符和重定向

    【Linux】文件的描述符和重定向

    C語(yǔ)言的文件讀寫操作 文件寫入 fputs int fputs(const char *s, FILE *stream); s:要寫入的字符串 stream:要寫入對(duì)應(yīng)的目標(biāo)文件 文件輸出(只可以在文件讀的環(huán)境下運(yùn)行 r) fgets char *fgets(char *s, int size, FILE *stream); s:要保存到的目標(biāo)位置 size:輸出多少字節(jié) stream:輸出的目標(biāo)文件 文件寫

    2024年02月12日
    瀏覽(22)
  • Linux中的文件描述符和重定向

    Linux中的文件描述符和重定向

    文件描述符概念 我們?cè)谑褂孟到y(tǒng)調(diào)用進(jìn)行文件操作的時(shí)候 這里的open返回值就是一個(gè)文件描述符簡(jiǎn)稱fd。 文件描述符其實(shí)就是一個(gè)從3開始的小整數(shù),文件描述符是小整數(shù)的原因是因?yàn)槲募枋龇麑?shí)際是文件描述符表這個(gè)數(shù)組的下標(biāo)。 為什么從3開始,是因?yàn)橄到y(tǒng)默認(rèn)打開了三

    2023年04月10日
    瀏覽(31)
  • 『Linux』文件描述符及重定向——為何說Linux下,一切皆文件?

    『Linux』文件描述符及重定向——為何說Linux下,一切皆文件?

    ??作者簡(jiǎn)介: 花想云 ,在讀本科生一枚,C/C++領(lǐng)域新星創(chuàng)作者,新星計(jì)劃導(dǎo)師,阿里云專家博主,CSDN內(nèi)容合伙人…致力于 C/C++、Linux 學(xué)習(xí)。 ?? 專欄簡(jiǎn)介:本文收錄于 Linux從入門到精通 ,本專欄主要內(nèi)容為本專欄主要內(nèi)容為L(zhǎng)inux的系統(tǒng)性學(xué)習(xí),專為小白打造的文章專欄。

    2024年02月12日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包