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

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

這篇具有很好參考價(jià)值的文章主要介紹了系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。


C文件接口

C文件接口

C文件接口都是封裝了系統(tǒng)的文件接口,學(xué)習(xí)系統(tǒng)的文件接口有利于更熟悉文件的操作。

系統(tǒng)文件I/O

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)建的目標(biāo)文件
flags: 打開文件時(shí),可以傳入多個(gè)參數(shù)選項(xiàng),用下面的一個(gè)或者多個(gè)常量進(jìn)行“或”運(yùn)算,構(gòu)成flags。
參數(shù):
O_RDONLY: 只讀打開
O_WRONLY: 只寫打開
O_RDWR : 讀,寫打開
這三個(gè)常量,必須指定一個(gè)且只能指定一個(gè)
O_CREAT : 若文件不存在,則創(chuàng)建它。需要使用mode選項(xiàng),來指明新文件的訪問權(quán)限
O_APPEND: 追加寫

返回值:
成功:新打開的文件描述符
失?。?1

open函數(shù)具體使用哪個(gè),和具體應(yīng)用場景相關(guān),如目標(biāo)文件不存在,則第三個(gè)參數(shù)表示創(chuàng)建文件的默認(rèn)權(quán)限,否則只使用前兩個(gè)參數(shù)。

打開文件的本質(zhì)就是將需要的文件屬性加載到內(nèi)存中,OS內(nèi)部一定會(huì)存在大量被打開的文件,那么操作系統(tǒng)如何管理被打開的文件?先描述,再組織。

先描述,構(gòu)建在內(nèi)存中的文件結(jié)構(gòu)體struct file(文件屬性,struct file*),每一個(gè)被打開的文件,都要在OS內(nèi)構(gòu)建對(duì)應(yīng)的文件對(duì)象的struct結(jié)構(gòu)體,再組織,即將所有的struct file結(jié)構(gòu)體使用某種數(shù)據(jù)結(jié)構(gòu)如鏈表去鏈接起來。

在OS內(nèi)部,對(duì)被打開的文件進(jìn)行管理,就被轉(zhuǎn)換為了對(duì)鏈表的增刪查改。

結(jié)論:文件被打開,OS要為被打開的文件,構(gòu)建對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu)。

struct file
{
//各自屬性
//各種鏈接關(guān)系
};

文件可以分為兩大類:磁盤文件,被打開的文件(內(nèi)存文件)。

文件被打開,是誰在打開呢?OS,但是是誰讓打開的?用戶(進(jìn)程為代表的),我們之前的所有文件操作,都是進(jìn)程和被打開文件的關(guān)系,即struct task_struct 和 struct file的關(guān)系。

open函數(shù)的使用例子

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>


#define LOG "log.txt"

int main()
{
    int fd = open(LOG,O_WRONLY);//打開文件,表示只進(jìn)行寫入,如果沒有該文件,會(huì)打開失敗
    if(fd == -1)
    {
        printf("errno : %d , error : %s\n",errno,strerror(errno));
        exit(-1);
    }
    close(fd);
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
沒有l(wèi)og.txt文件,打開失敗。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>


#define LOG "log.txt"

int main()
{
    int fd = open(LOG,O_WRONLY | O_CREAT);//打開文件,表示只進(jìn)行寫入,加入標(biāo)準(zhǔn)O_CREAT表示沒有該文件就進(jìn)行創(chuàng)建
    if(fd == -1)
    {
        printf("errno : %d , error : %s\n",errno,strerror(errno));
        exit(-1);
    }
    close(fd);
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
雖然open函數(shù)創(chuàng)建了log.txt文件,但是ls顯示的時(shí)候,該文件卻標(biāo)紅,這是為什么呢?這是在創(chuàng)建的時(shí)候,沒有設(shè)置權(quán)限,導(dǎo)致權(quán)限出現(xiàn)了亂碼。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>


#define LOG "log.txt"

int main()
{
    int fd = open(LOG,O_WRONLY | O_CREAT,0666);//打開文件,表示只進(jìn)行寫入,加入標(biāo)準(zhǔn)O_CREAT表示沒有該文件就進(jìn)行創(chuàng)建
    if(fd == -1)                               //加入權(quán)限0666
    {
        printf("errno : %d , error : %s\n",errno,strerror(errno));
        exit(-1);
    }
    close(fd);
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
此時(shí),創(chuàng)建成功,權(quán)限也不會(huì)出現(xiàn)亂碼,但是權(quán)限卻是664,而不是666,這又是受到權(quán)限掩碼的影響。

詳細(xì)看文章的文件權(quán)限

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>


#define LOG "log.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為0即可
    int fd = open(LOG,O_WRONLY | O_CREAT,0666);//打開文件,表示只進(jìn)行寫入,加入標(biāo)準(zhǔn)O_CREAT表示沒有該文件就進(jìn)行創(chuàng)建
    if(fd == -1)                               //加入權(quán)限0666
    {
        printf("errno : %d , error : %s\n",errno,strerror(errno));
        exit(-1);
    }
    close(fd);
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

這里的權(quán)限就是666了。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>


#define LOG "log.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為0即可
    int fd = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);//打開文件,表示只進(jìn)行寫入,加入標(biāo)準(zhǔn)O_CREAT表示沒有該文件就進(jìn)行創(chuàng)建
    if(fd == -1)                               //加入權(quán)限0666,加入O_TRUNC表示打開文件時(shí)會(huì)對(duì)文件進(jìn)行清空
    {                       
        printf("errno : %d , error : %s\n",errno,strerror(errno));
        exit(-1);
    }
    close(fd);
    return 0;
}

O_TRUNC表示每次打卡文件都會(huì)進(jìn)行清空,它會(huì)O_APPEND即追加不會(huì)同時(shí)出現(xiàn),因?yàn)閮烧呦噙`。

open函數(shù)的flag標(biāo)志
open函數(shù)的flag標(biāo)志本質(zhì)是一個(gè)位圖結(jié)構(gòu),比如一個(gè)int就可以同時(shí)傳遞32個(gè)標(biāo)記位,操作系統(tǒng)會(huì)去遍歷這個(gè)位圖,查看哪個(gè)位置是1,再進(jìn)行相應(yīng)的操作。比如是否清空,就表示位圖某個(gè)位置是否置1。

系統(tǒng)調(diào)用和庫函數(shù)

fopen fclose fread fwrite 都是C標(biāo)準(zhǔn)庫當(dāng)中的函數(shù),我們稱之為庫函數(shù)(libc),而 open close read write lseek 都屬于系統(tǒng)提供的接口,稱之為系統(tǒng)調(diào)用口。

所以,可以認(rèn)為,f#系列的函數(shù),都是對(duì)系統(tǒng)調(diào)用的封裝,方便二次開發(fā)。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
這些函數(shù)直接man指令查詢即可,與C庫文件操作大同小異。

文件描述符

通過對(duì)open函數(shù)的學(xué)習(xí),我們知道了文件描述符就是一個(gè)小整數(shù)

0 & 1 & 2

Linux進(jìn)程默認(rèn)情況下會(huì)有3個(gè)缺省打開的文件描述符,分別是標(biāo)準(zhǔn)輸入0, 標(biāo)準(zhǔn)輸出1, 標(biāo)準(zhǔn)錯(cuò)誤2。0,1,2對(duì)應(yīng)的物理設(shè)備一般是:鍵盤,顯示器,顯示器。

任何一個(gè)進(jìn)程,在啟動(dòng)的時(shí)候,默認(rèn)會(huì)打開當(dāng)前進(jìn)程的三個(gè)文件。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

C語言中:
extern FILE* stdin
extern FILE* stdout
extern FILE* stderr

我們打開一個(gè)文件,可以發(fā)現(xiàn)文件描述符是從3開始的。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>


#define LOG "log.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為
    int fd = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    if(fd == -1)                          
    {                       
        printf("errno : %d , error : %s\n",errno,strerror(errno));
        exit(-1);
    }
    printf("文件描述符:%d\n",fd);
    close(fd);
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
為什么文件描述符從3開始呢,0、1、2代表著什么,三個(gè)默認(rèn)打開的文件流。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
Linux下一切皆文件,所以向顯示器打印,本質(zhì)是向文件寫入。

#include <cstdio>
#include <iostream>

int main()
{
    printf("hello printf->stdout\n");
    fprintf(stdout,"hello fprintf->stdout\n");
    fprintf(stderr,"hello fprintf->stderr\n");

    //c++
    std::cout << "hello cout->cout" << std::endl;
    std::cerr << "hello cerr->cerr" << std::endl;

    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)錯(cuò)誤都會(huì)向顯示器打印,但是其實(shí)是不一樣的。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
標(biāo)準(zhǔn)輸出會(huì)受到重定向的影響,標(biāo)準(zhǔn)錯(cuò)誤不會(huì)受到重定向的影響。

進(jìn)程如何管理打開的文件?

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

文件描述符就是從0開始的小整數(shù)。當(dāng)我們打開文件時(shí),操作系統(tǒng)在內(nèi)存中要?jiǎng)?chuàng)建相應(yīng)的數(shù)據(jù)結(jié)構(gòu)來描述目標(biāo)文件。于是就有了file結(jié)構(gòu)體。表示一個(gè)已經(jīng)打開的文件對(duì)象。而進(jìn)程執(zhí)行open系統(tǒng)調(diào)用,所以必須讓進(jìn)程和文件關(guān)聯(lián)起來。每個(gè)進(jìn)程都有一個(gè)指針*files, 指向一張表files_struct,該表最重要的部分就是包涵一個(gè)指針數(shù)組,每個(gè)元素都是一個(gè)指向打開文件的指針!所以,本質(zhì)上,文件描述符就是該數(shù)組的下標(biāo)。所以,只要拿著文件描述符,就可以找到對(duì)應(yīng)的文件。

如何理解Linux下一切皆文件?

我們使用OS的本質(zhì):都是通過進(jìn)程的方式進(jìn)行OS的訪問的。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
在所有的外設(shè)上鋪上一層軟件層,即寫函數(shù)和讀函數(shù),根據(jù)需要來設(shè)計(jì)這些函數(shù),在上層,用struct file來管理這些函數(shù),所以在Linux看來,一切皆文件。

FILE和fd的關(guān)系

FILE是什么?結(jié)構(gòu)體。
誰提供的?C語言提供的。
和我們剛才提供的內(nèi)核struct file有關(guān)系?——沒有任何關(guān)系,上下層關(guān)系。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

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

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>

#define LOG "log.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為
    int fd1 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd2 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd3 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd4 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd5 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd6 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);

    printf("%d\n",fd1);
    printf("%d\n",fd2);
    printf("%d\n",fd3);
    printf("%d\n",fd4);
    printf("%d\n",fd5);
    printf("%d\n",fd6);

    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
因?yàn)?、1、2是默認(rèn)打開的三個(gè)文件流,所以是文件描述符是從3開始打開的。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>

#define LOG "log.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為
    close(0);//關(guān)閉0號(hào)文件描述符
    int fd1 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd2 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd3 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd4 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd5 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd6 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);

    printf("%d\n",fd1);
    printf("%d\n",fd2);
    printf("%d\n",fd3);
    printf("%d\n",fd4);
    printf("%d\n",fd5);
    printf("%d\n",fd6);

    return 0;
}

關(guān)閉0號(hào)文件描述符,程序運(yùn)行的結(jié)果:

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>

#define LOG "log.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為
    close(0);//關(guān)閉0號(hào)文件描述符
    close(2);//關(guān)閉2號(hào)文件描述符
    int fd1 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd2 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd3 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd4 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd5 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fd6 = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);

    printf("%d\n",fd1);
    printf("%d\n",fd2);
    printf("%d\n",fd3);
    printf("%d\n",fd4);
    printf("%d\n",fd5);
    printf("%d\n",fd6);

    return 0;
}

關(guān)閉0號(hào)文件描述符和2號(hào)描述符,程序運(yùn)行的結(jié)果:

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
進(jìn)程中,文件描述符的分配規(guī)則:在文件描述符表中,最小的沒有被使用的數(shù)組元素,分配給新文件。

重定向

重定向的本質(zhì)

輸出重定向
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>

#define LOG "log.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為
    close(1);//關(guān)閉1號(hào)文件描述符
    int fd = open(LOG,O_WRONLY | O_CREAT | O_TRUNC,0666);

    printf("you can see me!\n");
    printf("you can see me!\n");
    printf("you can see me!\n");
    printf("you can see me!\n");
    printf("you can see me!\n");
    printf("you can see me!\n");
    printf("you can see me!\n");
    printf("you can see me!\n");
    printf("you can see me!\n");
    printf("you can see me!\n");
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
程序運(yùn)行之后并沒有結(jié)果,但是打印log.txt文件內(nèi)容的時(shí)候,卻發(fā)現(xiàn)了程序運(yùn)行的結(jié)果。

這其實(shí)已經(jīng)發(fā)生重定向。

程序首先關(guān)閉了1號(hào)文件,再打開log.txt,根據(jù)文件描述符的分配規(guī)則,log.txt將被分配到1號(hào)文件描述符。

printf往文件描述符為1(即標(biāo)準(zhǔn)輸出)進(jìn)行打印,但是底層文件描述符為1的指向從標(biāo)準(zhǔn)輸出被替換為log.txt,所以出現(xiàn)了不往顯示器打印,而是往log.txt文件輸出。(重定向的本質(zhì))

重定向的原理:在上層無法感知的情況下,在OS內(nèi)部,更改進(jìn)程對(duì)應(yīng)的文件描述符表中的下標(biāo)的指向。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

輸入重定向

將log.txt文件改為123 456
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>

#define LOG "log.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為
    close(0);//關(guān)閉0號(hào)文件描述符
    int fd = open(LOG,O_RDONLY,0666);//注意改為只讀

    int a,b;
    scanf("%d %d",&a,&b);
    printf("a=%d,b=%d\n",a,b);
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
原理一樣,關(guān)閉0號(hào)文件描述符,打開log.txt文件,那么0號(hào)文件描述符就指向log.txt文件,即從log.txt獲取結(jié)果輸入到變量a和變量b中。

圖形跟上一張圖差不多。只不過是標(biāo)準(zhǔn)輸入指向的新文件。

追加重定向

讓標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤分開輸出到不同文件,方便排查錯(cuò)誤。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>

#define LOG_NORWAL "logNormal.txt"
#define LOG_ERROR "logERROR.txt"

int main()
{
    umask(0);//這里將權(quán)限掩碼設(shè)置為
    close(1);//關(guān)閉0號(hào)文件描述符
    open(LOG_NORWAL,O_WRONLY | O_CREAT | O_APPEND,0666);//注意改為追加

    close(2);
    open(LOG_ERROR,O_WRONLY | O_CREAT | O_APPEND,0666);//注意改為追加
    
    printf("printf->stdout\n");//正確結(jié)果
    fprintf(stdout,"fprintf->stdout\n");//正確結(jié)果
    fprintf(stderr,"fprintf->stderr\n");//錯(cuò)誤
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
重定向也可以通過指令來實(shí)現(xiàn),常見的重定向有:>, >>, <。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>

int main()
{   
    printf("printf->stdout\n");//正確結(jié)果
    fprintf(stdout,"fprintf->stdout\n");//正確結(jié)果
    fprintf(stderr,"fprintf->stderr\n");//錯(cuò)誤
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

stdout、cout都是向1號(hào)文件描述符對(duì)應(yīng)的文件打印。
stderr、cerr都是向2號(hào)文件描述符對(duì)應(yīng)的文件打印。

dup2函數(shù)

dup、dup2、dup3函數(shù)都是改變文件描述符的指向。

dup2(3,1);//將文件描述符1指向改為與文件描述符3指向相同,關(guān)閉文件描述符3的指向。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <cerrno>
#include <string.h>
#include <unistd.h>
#include <iostream>

#define LOG "log.txt"

int main()
{   
    umask(0);
    int fd = open(LOG,O_CREAT | O_WRONLY | O_APPEND,0666);
    if(fd < 0)
    {
        perror("open");
        exit(1);
    }    
    dup2(fd,1);//將文件描述符1的指向改成與fd指向相同,關(guān)閉文件描述符fd的指向,間接完成了輸出重定向
    printf("hello world\n");
    close(fd);
    return 0;
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

FILE

我們先看一個(gè)程序。

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define LOG "log.txt"

int main()
{   
    fprintf(stdout,"hello fprintf\n");

    const char* msg = "hello write\n";
    write(1,msg,strlen(msg));
    fork();
    return 0;
}

正常運(yùn)行下:

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
輸出重定向下:

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
輸出重定向下,fprintf居然多打印了一次。這是為什么呢?

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

C語言會(huì)結(jié)合一定刷新策略,將我們?cè)贑庫緩沖區(qū)中的數(shù)據(jù)寫到files_struct[fd]指向的緩沖區(qū),再由OS結(jié)合一定的刷新策略,將files_struct[fd]指向的緩沖區(qū)寫到磁盤上。

C語言的刷新策略:
1.無緩沖
2.行緩沖(遇到\n就刷新)
3.全緩沖(緩沖區(qū)滿了就刷新)

1.顯示器采用的刷新策略:行緩沖。
2.普通文件采用的刷新策略:全緩沖。
3.緩沖區(qū)在哪里,在你進(jìn)行fopen打開文件的時(shí)候,你會(huì)得到FILE結(jié)構(gòu)體,緩沖區(qū)就在這個(gè)FILE結(jié)構(gòu)體中。
4.為什么要有緩沖區(qū),節(jié)省調(diào)用者的時(shí)間(調(diào)用刷新函數(shù)是系統(tǒng)調(diào)用)(系統(tǒng)調(diào)用也要花費(fèi)時(shí)間)(減少頻繁調(diào)用,采用一次性刷新大量數(shù)據(jù))。

解釋現(xiàn)象

一開始只是運(yùn)行程序,未重定向,結(jié)果為hello fprintf和hello write。
原因:fprintf是輸入到顯示器,顯示器是行刷新,所以當(dāng)把hello fprintf輸入到C庫中的緩沖區(qū)中,因?yàn)橛小痋n’,所以會(huì)直接刷新到操作系統(tǒng)的緩沖區(qū)中,而write是系統(tǒng)調(diào)用,會(huì)直接刷新到操作系統(tǒng)的緩沖區(qū)中,綜上,當(dāng)fork的時(shí)候,C庫的輸出緩沖區(qū)已經(jīng)沒有內(nèi)容了。

當(dāng)輸出重定向到普通文件時(shí),普通文件是全刷新,而一行的hello fprintf\n并不會(huì)使C庫的輸出緩沖區(qū)滿了,所以hello fprintf\n不會(huì)被刷新到操作系統(tǒng)的緩沖區(qū)中,而write是系統(tǒng)調(diào)用,會(huì)直接刷新到系統(tǒng)的緩沖區(qū)中,所以,fork的時(shí)候,C庫的緩沖區(qū)還要內(nèi)容hello fprintf\n,當(dāng)fork的時(shí)候,C庫的緩沖區(qū)還有內(nèi)容hello fprintf\n,那么父子進(jìn)程誰先進(jìn)行刷新C庫的緩沖區(qū),誰先發(fā)生寫實(shí)拷貝,那么父子進(jìn)程各刷新一次,就會(huì)輸出兩次hello fprintf\n。

綜上: printf fwrite 庫函數(shù)會(huì)自帶緩沖區(qū),而 write 系統(tǒng)調(diào)用沒有帶緩沖區(qū)。另外,我們這里所說的緩沖區(qū),都是用戶級(jí)緩沖區(qū)。其實(shí)為了提升整機(jī)性能,OS也會(huì)提供相關(guān)內(nèi)核級(jí)緩沖區(qū),不過不再我們討論范圍之內(nèi)。那這個(gè)緩沖區(qū)誰提供呢? printf fwrite 是庫函數(shù), write 是系統(tǒng)調(diào)用,庫函數(shù)在系統(tǒng)調(diào)用的“上層”, 是對(duì)系統(tǒng)調(diào)用的“封裝”,但是 write 沒有緩沖區(qū),而 printf fwrite 有,足以說明,該緩沖區(qū)是二次加上的,又因?yàn)槭荂,所以由C標(biāo)準(zhǔn)庫提供。

前面已經(jīng)說過,由OS結(jié)合一定的刷新策略,將files_struct[fd]指向的緩沖區(qū)寫到磁盤上,那么,我們?cè)趺磸?qiáng)制刷新內(nèi)核緩沖區(qū)呢?使用fsync函數(shù),就可以強(qiáng)制內(nèi)核緩沖區(qū)刷新數(shù)據(jù)到磁盤上。

int fsync(int fd);

理解文件系統(tǒng)

如果文件沒有被打開呢?那么文件會(huì)在哪里?一定不在內(nèi)存中,只能在磁盤等外設(shè)中靜靜的存儲(chǔ)著。

磁盤文件,如何沒有被打開,如何理解這些文件呢?需要解決什么問題?
需要解決合理存儲(chǔ)的問題,快速定位,快速讀取和寫入等問題。

了解磁盤的物理結(jié)構(gòu)

磁盤分為機(jī)械磁盤和SSD固態(tài)磁盤。

磁盤是計(jì)算機(jī)唯一的一個(gè)機(jī)械設(shè)備,同時(shí)它還是外設(shè)。外設(shè)和機(jī)械設(shè)備決定了它非常慢(相對(duì)CPU和內(nèi)存來說)。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

盤片:一片兩面,有一摞盤片,可以讀寫。
向磁盤寫入:盤片的某一些位置N->S
刪除磁盤數(shù)據(jù):磁盤的某一些位置S->N

磁頭:一個(gè)面一個(gè)磁頭,一個(gè)磁頭負(fù)責(zé)一面的讀取
磁頭:共進(jìn)退的。
磁頭和盤面是沒有挨著的,距離依舊很近。
對(duì)數(shù)據(jù)的寫入和讀取分別是更改某個(gè)位置的S、N或者讀取某個(gè)位置的S、N。

磁盤中存儲(chǔ)的基本元素:扇區(qū),512字節(jié)或者4kb字節(jié),一般磁盤,所有的扇區(qū)都是512字節(jié)。

同半徑的所有扇區(qū),稱為磁道。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
如何定位一個(gè)扇區(qū)?
首先確定哪一面,這里只需要確定哪一個(gè)磁頭的編號(hào)來確定是哪一面。
再定位哪一個(gè)磁道,由半徑?jīng)Q定。
再確定哪一個(gè)扇區(qū),根據(jù)扇區(qū)的編號(hào),確定一個(gè)扇區(qū)。

磁頭:head
柱面(磁道):cylinder
扇區(qū):sector

所以上面確定扇區(qū)的辦法為:CHS定位法

一個(gè)普通文件(屬性和數(shù)據(jù)),都是數(shù)據(jù)(0,1),無非就是占用一個(gè)或者多個(gè)扇區(qū),來進(jìn)行自己的數(shù)據(jù)存儲(chǔ)的。既然能用CHS方法定位任意一個(gè)扇區(qū),就可以定位任意多個(gè)扇區(qū),從而將文件從硬件角度,進(jìn)行讀取或者寫入。

邏輯抽象

如果OS能夠得知任意一個(gè)CHS地址,就能訪問任意一個(gè)扇區(qū)。那么OS內(nèi)部是直接使用CHS地址的么?不是。

1.OS是軟件,磁盤是硬件,磁盤定位一個(gè)地址,CHS,OS使用的話,如果硬件變了,OS也要發(fā)生變化,OS和磁盤沒有做好解耦的工作。
2。即使是扇區(qū),512字節(jié),定位的IO的基本數(shù)據(jù)也就很小,OS基本單位是4kb(可以調(diào)整),磁盤:塊設(shè)備,所以,OS要有一套新的地址,來進(jìn)行塊設(shè)備級(jí)別的訪問。

OS是以4kb為單位進(jìn)行IO的,故一個(gè)OS級(jí)別的文件塊要包括8個(gè)扇區(qū),甚至,在OS角度,它不關(guān)心扇區(qū)。

計(jì)算機(jī)常規(guī)的訪問方式:起始地址+偏移量(語言中的數(shù)據(jù)類型),只需要找到數(shù)據(jù)塊的起始地址(第一個(gè)扇區(qū)的下標(biāo)地址)+4kb(塊的類型),就可以定位一個(gè)數(shù)據(jù)塊。

OS采用LBA(邏輯塊地址),磁盤采用CHS地址,所以一直存在LBA和CHS相互轉(zhuǎn)換。

文件系統(tǒng)

文件系統(tǒng)的圖解和解析

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
Boot Block:保存與操作系統(tǒng)啟動(dòng)相關(guān)的內(nèi)容,諸如分區(qū)表和操作系統(tǒng)的鏡像的地址,一般該分區(qū)會(huì)在0號(hào)盤面的0號(hào)磁道的1號(hào)扇區(qū)里開始保存,對(duì)應(yīng)的一般在C盤的某個(gè)位置存在這樣的數(shù)據(jù),當(dāng)操作系統(tǒng)開機(jī)的時(shí)候,至少要做兩件事情,第一個(gè),找到磁盤這個(gè)設(shè)備,并加載磁盤的驅(qū)動(dòng)程序,第二個(gè)是加載分區(qū)表,識(shí)別出磁盤的C盤、D盤、F盤,再從分區(qū)的起始位置讀取操作系統(tǒng)的地址,然后找到操作系統(tǒng)在磁盤的位置,再加載操作系統(tǒng)。如果這個(gè)塊因?yàn)槟骋恍┰驅(qū)е聰?shù)據(jù)丟失,比如刮花了,那么操作系統(tǒng)就會(huì)掛掉。

Block Group:ext2文件系統(tǒng)會(huì)根據(jù)分區(qū)的大小劃分為數(shù)個(gè)Block Group。而每個(gè)Block Group都有著相同的結(jié)構(gòu)組成。

超級(jí)塊(Super Block):存放文件系統(tǒng)本身的結(jié)構(gòu)信息。記錄的信息主要有:bolck 和 inode的總量,未使用的block和inode的數(shù)量,一個(gè)block和inode的大小,最近一次掛載的時(shí)間,最近一次寫入數(shù)據(jù)的時(shí)間,最近一次檢驗(yàn)磁盤的時(shí)間等其他文件系統(tǒng)的相關(guān)信息。Super Block的信息被破壞,可以說整個(gè)文件系統(tǒng)結(jié)構(gòu)就被破壞了??偨Y(jié):1.文件系統(tǒng)的類型 2.整個(gè)分組的情況。

GDT,Group Descriptor Table:塊組描述符,描述塊組屬性信息

塊位圖(Block Bitmap):Block Bitmap中記錄著Data Block中哪個(gè)數(shù)據(jù)塊已經(jīng)被占用,哪個(gè)數(shù)據(jù)塊沒有被占用

inode位圖(inode Bitmap):每個(gè)bit表示一個(gè)inode是否空閑可用。

i節(jié)點(diǎn)表(inode Table):存放文件屬性 如 文件大小,所有者,最近修改時(shí)間等

數(shù)據(jù)區(qū):存放文件內(nèi)容



一般而言,一個(gè)文件內(nèi)部所有屬性的集合為inode節(jié)點(diǎn)(128字節(jié)),一個(gè)文件,一個(gè)inode,其中,即使是一個(gè)分區(qū),內(nèi)部也會(huì)存在大量的文件即會(huì)存在大量的inode節(jié)點(diǎn),一個(gè)group,需要有一個(gè)區(qū)域,來專門保存該group內(nèi)所有的inode節(jié)點(diǎn)——inode table。

分組內(nèi)部,可能會(huì)存在多個(gè)inode,需要將inode區(qū)分開來,每一個(gè)inode都會(huì)有自己的inode編號(hào),inode編號(hào),也屬于對(duì)應(yīng)文件的屬性id。

文件的內(nèi)容是變化的。文件系統(tǒng)采用數(shù)據(jù)塊來進(jìn)行文件內(nèi)容的保存,所以一個(gè)有效的文件,要保存內(nèi)容,就需要[1,n]個(gè)數(shù)據(jù)塊。

linux查找一個(gè)文件,是要根據(jù)inode編號(hào),來進(jìn)行文件查找的,包括讀取內(nèi)容。

一個(gè)inode對(duì)應(yīng)一個(gè)文件,而該文件inode屬性和該文件的數(shù)據(jù)塊是有映射關(guān)系的。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
文件=內(nèi)容+屬性
linux是將內(nèi)容和屬性分離的,都是以塊的形式,被保存在磁盤的某個(gè)位置的。
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
數(shù)組代表了該文件對(duì)應(yīng)的數(shù)據(jù)塊的編號(hào),比如Data blocks依次保存了該文件的位置是1、3、5、7、9,那么該數(shù)組存的是1、3、5、7、9。

操作系統(tǒng)加載一個(gè)文件的時(shí)候,一次會(huì)加載許多的inode Table,因?yàn)樗笮」潭ǎ⑶冶容^小,加載進(jìn)來以后,訪問哪個(gè)文件不著急,因?yàn)閕node Table有跟文件的映射關(guān)系,需要讀取文件的哪一塊,再根據(jù)inode屬性里面的數(shù)組,在塊里面去找,拿到lba轉(zhuǎn)換成chs去訪問磁盤。

ls -il //查看文件的inode

通過文件系統(tǒng)來理解ls -al

ls -al查文件,那么文件的查是怎么操作的呢?當(dāng)ls進(jìn)程跑起來,它所處的路徑和目錄已知,那么通過該目錄(目錄也是文件)的inode與數(shù)據(jù)塊的對(duì)應(yīng)關(guān)系,找到該目錄存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)塊,找到對(duì)應(yīng)的文件名和inode的映射關(guān)系,找到inode,然后在自己特定的分區(qū)中找到對(duì)應(yīng)的inode數(shù)據(jù)。

目錄的數(shù)據(jù)塊存儲(chǔ)著該目錄下的文件和inode的對(duì)應(yīng)關(guān)系。

  1. inode vs 文件名
    linux系統(tǒng)只認(rèn)識(shí)inode編號(hào),文件的inode屬性中,并不存在文件名,文件名,只是給用戶用的。
  2. 重新認(rèn)識(shí)目錄
    目錄是文件嗎?是的。目錄有inode嗎?有。
    有內(nèi)容嗎?有。
    內(nèi)容是什么?
  3. 任何一個(gè)文件,一定在一個(gè)目錄的內(nèi)部,所以目錄的內(nèi)容是什么呢?存儲(chǔ)需要數(shù)據(jù)塊,目錄的數(shù)據(jù)塊里面保存的是該目錄下的文件名和文件inode編號(hào)的對(duì)應(yīng)的映射關(guān)系,而且,在目錄內(nèi),文件名和inode互為key值。
  4. 當(dāng)我們?cè)L問一個(gè)文件的時(shí)候,我們是在特定的目錄下訪問的 cat log.txt

a.先要在當(dāng)前目錄下,找到log.txt的inode編號(hào)。
b.一個(gè)目錄也是一個(gè)文件,也一定隸屬于一個(gè)分區(qū),結(jié)合inode,在該分區(qū)中找到分組,在該分組中inode table中,找到文件的inode。
c.通過inode和對(duì)應(yīng)的data blocks的映射關(guān)系,找到該文件的數(shù)據(jù)塊,并加載到OS,并完全顯示到顯示器。

通過文件系統(tǒng)來理解文件增刪查改
刪除一個(gè)文件

1.根據(jù)文件名在該文件所在目錄的數(shù)據(jù)塊找到對(duì)應(yīng)的inode編號(hào)
2.經(jīng)過inode與data blocks的映射關(guān)系,設(shè)置block bitmap對(duì)應(yīng)的比特位,置0就可以
3.inode,設(shè)置對(duì)應(yīng)的inode bitmap對(duì)應(yīng)的比特位為0

總結(jié):刪除文件只需要修改位圖即可。

增加一個(gè)文件

當(dāng)增加文件的時(shí)候,首先在一個(gè)特定的目錄下創(chuàng)建,操作系統(tǒng)就要在該目錄所在某一個(gè)分組中,先去查inode bitmap,從低比特位向高比特位掃描,找到為0的比特位,把它置為1,置1的同時(shí)根據(jù)是第幾個(gè)比特位,得到新的inode編號(hào),然后把文件相關(guān)的屬性填到inode Table中的inode表中,文件剛開始是空的,所以沒有數(shù)據(jù)塊,找到目錄的數(shù)據(jù)塊,追加一條新的文件名和inode的映射關(guān)系,然后這個(gè)文件就創(chuàng)建好了,未來你想對(duì)文件做修改和寫入的時(shí)候,拿到文件名找映射關(guān)系,然后找到該文件的inode,分配Data blocks,操作系統(tǒng)就會(huì)即使想要刷新的數(shù)據(jù)有多大,再申請(qǐng)若干個(gè)數(shù)據(jù)塊,并把block bitmap對(duì)應(yīng)的位置置為1,最后進(jìn)行刷新數(shù)據(jù)。

查找一個(gè)文件

如find指令,操作系統(tǒng)會(huì)在特定的目錄下,通過該目錄的inode與data blocks的映射關(guān)系,找到對(duì)應(yīng)的數(shù)據(jù)塊,可查看該目錄下的inode和文件名的映射關(guān)系,找到想要查找的文件,便可以得知該文件的屬性(inode)和內(nèi)容(對(duì)應(yīng)的data blocks)。

修改一個(gè)文件

在特定的目錄下,通過該目錄的inode與data blocks的映射關(guān)系,找到該目錄下的數(shù)據(jù)塊,可查到該目錄下inode和文件名的映射關(guān)系,查到想要修改的文件的inode,通過inode與data blocks的對(duì)應(yīng)關(guān)系,找到該文件的數(shù)據(jù)塊,便可以進(jìn)行修改,修改后,操作系統(tǒng)自動(dòng)修正inode的屬性。

補(bǔ)充細(xì)節(jié)
  1. 如果文件被誤刪了,該怎么辦?
    文件被誤刪了,那么就不要?jiǎng)?chuàng)建新的文件和目錄,因?yàn)楸徽`刪文件的位圖由1變?yōu)?,意味著該文件對(duì)應(yīng)的inode節(jié)點(diǎn)和數(shù)據(jù)塊隨時(shí)都會(huì)被新的文件占用,所以文件誤刪,最好的做法就是什么都不要干(即不要把數(shù)據(jù)和屬性覆蓋),如果能力允許的話,利用一些工具,找到被刪文件的inode編號(hào),通過inode編號(hào)找到特定的分組,然后將inode bitmap對(duì)應(yīng)的比特位由0置為1,然后讀取inode表,提取讀取文件占有的數(shù)據(jù)塊,然后將對(duì)應(yīng)的數(shù)據(jù)塊的block bitmap置1。

  2. inode,確定分組,inode是在一個(gè)分區(qū)唯一有效的,不能跨分區(qū)。(每個(gè)分區(qū)都有自己的文件系統(tǒng))

  3. 分區(qū)和分組,填寫系統(tǒng)屬性是誰做的呢?OS做的。什么時(shí)候做的呢?分區(qū)完成之后,要讓分區(qū)能夠被正常使用,我們需要對(duì)分區(qū)做格式化處理。格式化的過程,其實(shí)是OS向分區(qū)寫入文件系統(tǒng)的管理屬性信息。

  4. 如果inode只是單單的用數(shù)組建立和data block的映射關(guān)系,15 * 4kb = 60kb(假設(shè)一個(gè)datablock數(shù)組有15個(gè)元素),是不是意味著一個(gè)文件最多放入60kb。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

格式化時(shí),如果整個(gè)分區(qū)從來沒有格式化過,那么格式化,需要去寫數(shù)據(jù)區(qū)(從SB到Data blocks),如果當(dāng)前有數(shù)據(jù)區(qū),格式化的時(shí)候只需要將位圖結(jié)構(gòu)清空,屬性字段(sb、gdt)設(shè)置為初始狀態(tài)就可以了。inode table和data blocks不管。

Linux對(duì)于刪除文件會(huì)有一個(gè)日志,該日志會(huì)記錄文件名和inode,這個(gè)日志會(huì)保留一段時(shí)間。

每個(gè)分區(qū)的都有一套inode機(jī)制,inode不能跨分區(qū)使用,inode怎么確定分組呢?比如inode有100萬個(gè),那么可能把10萬個(gè)inode分配給第一個(gè)分組,那么只要0到10萬減一的inode就在第一個(gè)分組

  1. 有沒有可能,一個(gè)組的數(shù)據(jù)塊沒用完,inode沒了,或者inode沒用完,data blocks用完了?

有可能,比如在分區(qū)中創(chuàng)建大量的空文件,那不就是在消耗inode么。建造一個(gè)文件,瘋狂的往該文件塞大量的數(shù)據(jù),不就是在消耗data blocks么。

操作系統(tǒng)啟動(dòng)時(shí),預(yù)加載除了data blocks的其它內(nèi)容。

軟硬鏈接

1.制造軟硬鏈接,對(duì)比差別
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
軟鏈接文件的名字應(yīng)該是my_soft。

軟鏈接是一個(gè)獨(dú)立的鏈接文件,有自己的inode number,必有自己的inode屬性和內(nèi)容,其中內(nèi)容放的是自己所指向文件的路徑,類似windows的快捷方式。

硬鏈接是和目標(biāo)文件共用一個(gè)inode number,意味著硬鏈接一定和目標(biāo)文件使用同一個(gè)inode的,硬鏈接沒有獨(dú)立的inode。那硬鏈接干了什么?建立了新的文件名和老的inode的映射關(guān)系。

硬鏈接,采用引用計(jì)數(shù),當(dāng)引用計(jì)數(shù)為0時(shí),才真正刪除文件,不然都是引用計(jì)數(shù)減一。

unlink my_hard 刪除硬鏈接,unlink可用來刪除普通文件。

2.軟硬鏈接的使用場景
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
在ls查詢中,權(quán)限后面跟的數(shù)字就是引用計(jì)數(shù),硬鏈接某個(gè)文件以后,該文件的這個(gè)數(shù)字會(huì)增加。

3.補(bǔ)充知識(shí)
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
在創(chuàng)建一個(gè)新的目錄的時(shí)候引用計(jì)數(shù)是2,是因?yàn)樵瓉砦募cinode的映射關(guān)系和.文件名和inode的映射關(guān)系。

ls -di //-d 將文件像目錄一樣顯示 -i 輸出文件索引,也就是inode

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
不能給目錄建立硬鏈接,為什么?
因?yàn)槿菀自斐森h(huán)路路徑問題。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

假如我從根目錄開始,進(jìn)行深度優(yōu)先遍歷查找,當(dāng)查找到/home/zrb/107/test的時(shí)候,再往link_hard目錄查找的時(shí)候,又因?yàn)閘ink_hard是test的硬鏈接,所以本質(zhì)是又回到了test目錄,又再往link_hard的目錄查找,導(dǎo)致了深度優(yōu)先遍歷一直卡在了這條查找路徑上。

上級(jí)目錄…本質(zhì)也是一種環(huán)路路徑問題,/home/zrb/107/test/. . 注意. .是在下一個(gè)目錄里面的,表示當(dāng)前目錄的,所以還是跟上面的情況是一樣的,深度優(yōu)先遍歷的時(shí)候從test目錄進(jìn)去. .目錄,但由于. .目錄是test目錄的硬鏈接,所以本質(zhì)又是回到了test目錄,繼續(xù)往. .目錄遍歷,導(dǎo)致一直卡在了這條搜索路徑,但是,操作系統(tǒng)會(huì)對(duì)遇到. .進(jìn)行特殊處理,所以才不會(huì)死循環(huán)查找。

文件的三種時(shí)間

Access 最后訪問時(shí)間
Modify 文件內(nèi)容最后修改時(shí)間
Change 屬性最后修改時(shí)間

增刪查改中,查的頻率是最高的,如果高頻次的對(duì)文件最后訪問時(shí)間做修改的話,一定意味著高頻次的將修改后的時(shí)間刷新到磁盤外設(shè)中,將提高系統(tǒng)刷新的IO頻次,進(jìn)而導(dǎo)致效率降低,所以在最新的內(nèi)核中把查看的時(shí)間修改策略改變了,也就是不一定每次查看都要修改文件最后訪問時(shí)間,可能每隔上三五次刷新一層,不同的操作系統(tǒng)的刷新策略不同,進(jìn)而減少內(nèi)存和磁盤IO交涉的成本,修改時(shí)間每次都要刷新,訪問數(shù)據(jù)不修改文件內(nèi)容和屬性,即使丟失了,也沒有關(guān)系,但是修改時(shí)間丟失了,就有問題了。

動(dòng)態(tài)庫和靜態(tài)庫

靜態(tài)庫(.a):程序在編譯鏈接的時(shí)候把庫的代碼鏈接到可執(zhí)行文件中。程序運(yùn)行的時(shí)候?qū)⒉辉傩枰o態(tài)庫

動(dòng)態(tài)庫(.so):程序在運(yùn)行的時(shí)候才去鏈接動(dòng)態(tài)庫的代碼,多個(gè)程序共享使用庫的代碼。

一個(gè)與動(dòng)態(tài)庫鏈接的可執(zhí)行文件僅僅包含它用到的函數(shù)入口地址的一個(gè)表,而不是外部函數(shù)所在目標(biāo)文件的整個(gè)機(jī)器碼

在可執(zhí)行文件開始運(yùn)行以前,外部函數(shù)的機(jī)器碼由操作系統(tǒng)從磁盤上的該動(dòng)態(tài)庫中復(fù)制到內(nèi)存中,這個(gè)過程稱為動(dòng)態(tài)鏈接(dynamic linking)

動(dòng)態(tài)庫可以在多個(gè)程序間共享,所以動(dòng)態(tài)鏈接使得可執(zhí)行文件更小,節(jié)省了磁盤空間。操作系統(tǒng)采用虛擬內(nèi)存機(jī)制允許物理內(nèi)存中的一份動(dòng)態(tài)庫被要用到該庫的所有進(jìn)程共用,節(jié)省了內(nèi)存和磁盤空間。

頭文件和庫的關(guān)系

1.系統(tǒng)已經(jīng)預(yù)裝了c/c++的頭文件和庫文件,頭文件提高方法說明,庫提高方法的實(shí)現(xiàn),頭和庫是有對(duì)應(yīng)關(guān)系的,是要組合在一起使用的。
2.頭文件是在預(yù)處理階段引入的,鏈接的本質(zhì)是鏈接庫。

理解現(xiàn)象:
a.在vs2019、vs2022下安裝開發(fā)環(huán)境——安裝編輯器軟件、安裝要開發(fā)的語言配套的庫和頭文件。

b.我們?cè)谑褂镁庉嬈鳎紩?huì)有語法的自動(dòng)提醒功能,需要先包含頭文件的。語法提醒的本質(zhì):編輯器會(huì)主動(dòng)的將用戶輸入的內(nèi)容,不斷的在被包含的頭文件中進(jìn)行搜索,自動(dòng)提醒功能是依賴頭文件的。

c.我們?cè)趯懘a的時(shí)候,我們的環(huán)境怎么知道我們的代碼有哪些地方有語法錯(cuò)誤,哪些地方定義變量有問題?編輯器有命令行模式和其他自動(dòng)化模式幫我們不斷的進(jìn)行語法檢查。

為什么要有庫

提高開發(fā)效率——可以選擇源代碼、或者編譯成二進(jìn)制代碼給別人。

寫一個(gè)庫

當(dāng)我們寫了一個(gè)庫,要將庫引入我們的項(xiàng)目,必須讓編輯器找到頭文件+庫文件。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
在下面的解釋中,全部按照自己實(shí)現(xiàn)了代碼,如何給別人使用的背景下來進(jìn)行操作。

目錄myself就是代表自己,目錄otherperson就是代表其他人
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
我在目錄myself實(shí)現(xiàn)了幾個(gè)函數(shù),如下
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
myadd.h文件

#ifndef __ADD_H__
#define __ADD_H__

int add(int a,int b);

#endif

myadd.c文件

#include "myadd.h"

int add(int a,int b)
{
    return a + b;
}

mysub.h

#ifndef __SUB_H__
#define __SUB_H__

int sub(int a,int b);

#endif

mysub.c

#include "mysub.h"

int sub(int a,int b)
{
    return a - b;
}

接下來就是如何將myself目錄下的文件給otherperson使用。

直接拷貝頭文件和源代碼給別人

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
此時(shí),其他人便可以調(diào)用函數(shù)的方式去實(shí)現(xiàn)。

#include <stdio.h>
#include "myadd.h"
#include "mysub.h"

int main()
{
    printf("%d\n",add(10,15));
    printf("%d\n",sub(20,15));
}

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
但是,一般來說,并不會(huì)直接把源代碼拷貝給其他人,保障知識(shí)產(chǎn)權(quán)。

將源代碼生成二進(jìn)制文件,拷貝給別人

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
其他人也可以通過這種方式使用你寫的函數(shù)
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

生成靜態(tài)庫,拷貝給別人

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
其他人也可以通過這種方式使用你寫的函數(shù)
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

生成靜態(tài)庫,壓縮發(fā)給別人

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
其他人通過解壓,便可以進(jìn)行調(diào)用我寫的函數(shù)了。

將頭文件拷貝到系統(tǒng)搜索頭文件的默認(rèn)搜索位置和將庫拷貝到庫的默認(rèn)搜索路徑下

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
其他直接表明使用的庫名字,便可以進(jìn)行調(diào)用我寫的函數(shù)了。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

生成動(dòng)態(tài)庫,拷貝給別人,別人將庫路徑導(dǎo)入環(huán)境變量當(dāng)中,讓操作系統(tǒng)可以查找,就可以運(yùn)行

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
別人便可以通過動(dòng)態(tài)庫,調(diào)用我寫的函數(shù)了

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

生成動(dòng)態(tài)庫,拷貝給別人,別人建立動(dòng)態(tài)庫的軟鏈接,就可以運(yùn)行

防止上面環(huán)境變量影響,可以重啟xshell。
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
別人便可以通過動(dòng)態(tài)庫,調(diào)用我寫的函數(shù)了

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

生成動(dòng)態(tài)庫,拷貝給別人,別人將動(dòng)態(tài)庫的路徑拷貝到配置文件里,就可以運(yùn)行

防止上面的軟鏈接影響,可以取消軟鏈接。
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
/etc/ld.so.conf:記錄了程序加載運(yùn)行期間查找動(dòng)態(tài)鏈接庫時(shí)的路徑。
ld:鏈接
so:動(dòng)態(tài)庫
conf:配置文件
配置文件里面放動(dòng)態(tài)庫的路徑。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
別人便可以通過動(dòng)態(tài)庫,調(diào)用我寫的函數(shù)了
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

第三方庫的使用

  1. 需要指定頭文件和庫文件
  2. 如果沒有默認(rèn)安裝到gcc、g++的默認(rèn)搜索路徑下,用戶必須指明對(duì)應(yīng)的選項(xiàng),告知編譯器:
    a.頭文件在哪里
    b.庫文件在哪里
    c.庫文件是誰
  3. 將我們下載下來的庫和頭文件,拷貝到系統(tǒng)的默認(rèn)搜索路徑下——就是在Linux下安裝庫。那么卸載呢?對(duì)任何軟件,安裝和卸載的本質(zhì)就是拷貝到系統(tǒng)特定的路徑下。
  4. 如果我們安裝的庫是第三方的(語言,操作系統(tǒng)系統(tǒng)接口)庫,我們要正常使用,即使是已經(jīng)全部安裝到了系統(tǒng)中,gcc/g++必須要用-l指明具體庫的名稱。

理解現(xiàn)象:在Linux安裝的大部分指令,都是需要sudo或者超級(jí)用戶操作的。

動(dòng)態(tài)庫配置

運(yùn)行時(shí),OS是如何查找動(dòng)態(tài)庫的

  1. 環(huán)境變量:LD_LIBRARY_PATH,每次打開xshell,環(huán)境變量都會(huì)被重新繼承,加入的環(huán)境變量會(huì)生效,所以是臨時(shí)方案。
  2. 軟鏈接方案
  3. 配置文件方案

在生成靜態(tài)庫,拷貝給別人的實(shí)驗(yàn)中,我們直接告訴編輯器庫在哪里,就可以運(yùn)行了,但是動(dòng)態(tài)庫這里,需要環(huán)境變量或者軟鏈接或者配置文件呢?

gcc -o myfile test.c -I include -L lib -lmymath

上面那條指令只是告訴了編譯器,沒有告訴OS,而上面三種方案,就是告訴OS,庫在哪里,但是,為什么靜態(tài)庫直接就可以運(yùn)行了呢?是因?yàn)椋o態(tài)庫,鏈接原則:將用戶使用的二進(jìn)制代碼直接拷貝到目標(biāo)可執(zhí)行程序中,但是動(dòng)態(tài)庫不會(huì)。

靜態(tài)庫的理解

靜態(tài)鏈接形成的可執(zhí)行程序,本身就有靜態(tài)庫中方法的實(shí)現(xiàn)(非常占用資源,可執(zhí)行程序體積變大,加載占用內(nèi)存,下載周期變長,占用網(wǎng)絡(luò)資源)

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

動(dòng)態(tài)庫的理解

將可執(zhí)行程序中的外部符號(hào),替換成為庫中的具體的地址。

假設(shè)程序用到了c庫的printf方法,并且當(dāng)前只有動(dòng)態(tài)庫

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
代碼1、代碼2、代碼3屬于mymath的代碼。

當(dāng)進(jìn)程開始沿著代碼1、代碼2往下執(zhí)行時(shí),遇到printf,經(jīng)過頁表映射,發(fā)現(xiàn)沒有printf代碼,所以整個(gè)進(jìn)程結(jié)合操作系統(tǒng)當(dāng)中立馬意識(shí)到這個(gè)程序依賴動(dòng)態(tài)庫,所以在當(dāng)前操作系統(tǒng)檢索動(dòng)態(tài)庫,將動(dòng)態(tài)庫中的printf方法load到內(nèi)存中,并且建立映射關(guān)系,映射到共享區(qū)中。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
執(zhí)行代碼1、代碼2,正常通過頁表映射,找到物理內(nèi)存中的mymath,執(zhí)行對(duì)應(yīng)的代碼,當(dāng)執(zhí)行到printf時(shí),操作系統(tǒng)就會(huì)檢測(cè)到printf已經(jīng)加載進(jìn)來,并映射成功,那么將從共享區(qū)找到printf的虛擬地址,通過頁表映射,找到物理內(nèi)存存儲(chǔ)的printf方法,運(yùn)行該printf方法,然后再回來運(yùn)行原有的代碼。

在加載printf方法時(shí),操作系統(tǒng)會(huì)以4kb為單位去加載,即操作系統(tǒng)會(huì)將printf函數(shù)上下文代碼也加載進(jìn)來,然后就可以加速其他進(jìn)程或者它自己代碼當(dāng)中還會(huì)用到printf周邊的方法,所以才會(huì)這樣加載。

只要把庫中對(duì)應(yīng)的方法加載到內(nèi)存,映射到進(jìn)程的地址空間之后,我們的代碼執(zhí)行庫中的方法,就依舊還是在自己的地址空間內(nèi)進(jìn)行函數(shù)跳轉(zhuǎn)即可。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
當(dāng)加載進(jìn)程B,進(jìn)程B依然使用了printf方法,當(dāng)進(jìn)程B使用printf,操作系統(tǒng)檢測(cè)到已經(jīng)加載了printf方法到物理內(nèi)存,此時(shí),直接將內(nèi)存中的printf方法映射到地址空間即可。其他進(jìn)程如果使用printf方法時(shí),也只是直接將內(nèi)存中的printf方法映射到地址空間即可,共享庫的所有公共方法在內(nèi)存里,最終只要一份就可以了,剩下的要用哪一些,就映射哪一些。

庫可能很大,平時(shí)進(jìn)程不一定會(huì)使用庫里面所有的方法,所以說把庫加載到內(nèi)存,不代表同時(shí)可以把庫全部加載到內(nèi)存里,需要哪一個(gè),就加載哪一個(gè),取決于操作系統(tǒng)的策略。

靜態(tài)庫和動(dòng)態(tài)庫加載進(jìn)地址空間的地址規(guī)律

在動(dòng)態(tài)庫加載中,不同的進(jìn)程,運(yùn)行程度是不同的,需要使用的第三方庫是不同的,注定了,每一個(gè)進(jìn)程的共享地址空間中的空閑位置是不確定的。如果采用固定地址映射,比如printf方法在進(jìn)程A映射的地址是0x11223344,但是在進(jìn)程B,0x11223344的地址空間已經(jīng)被用了,那么就沒有法映射0x11223344了。
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
在程序編譯鏈接形成可執(zhí)行程序的時(shí)候,可執(zhí)行程序內(nèi)部有沒有地址?有。進(jìn)程地址空間就已經(jīng)提到了。

絕對(duì)編址:例如,我在操場的50米左右。
相對(duì)編址:我在操場的樹的左邊大約20米。

系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
當(dāng)一個(gè)庫真正被映射進(jìn)地址空間的時(shí)候,它的起始地址才能真正確定。

調(diào)用printf的時(shí)候,只需要知道調(diào)用哪一個(gè)庫
如:這里調(diào)用lib.so庫
該庫的真正起始地址+123就可以找到printf方法

該庫的真正起始地址是什么?就是映射到進(jìn)程地址空間的起始地址。操作系統(tǒng)會(huì)記錄下來。

動(dòng)態(tài)庫,在進(jìn)程的地址空間中,隨便加載,與我們加載到進(jìn)程地址空間的什么位置,毫無關(guān)系了。

與位置無關(guān)碼:動(dòng)態(tài)庫中的地址都是偏移量。

好處:如庫有1萬個(gè)函數(shù),而這份代碼只用到其中100個(gè)方法,可以實(shí)現(xiàn)局部性加載,需要哪些,加載哪些。

動(dòng)態(tài)庫和靜態(tài)庫都存在,默認(rèn)動(dòng)態(tài)鏈接

在前面的操作中,已經(jīng)存在一些測(cè)試文件了。
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器
上面可以驗(yàn)證,動(dòng)態(tài)庫和靜態(tài)庫都存在,默認(rèn)動(dòng)態(tài)鏈接。

那么如何強(qiáng)制靜態(tài)鏈接呢?
系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫,Linux,linux,服務(wù)器

如果不提供動(dòng)態(tài)庫,只提供靜態(tài)庫,那么程序在進(jìn)行動(dòng)態(tài)鏈接的時(shí)候(沒有加-static),沒辦法,只能將庫以靜態(tài)鏈接的方式進(jìn)行鏈接,但是程序不僅僅鏈接一個(gè)庫,還要鏈接C庫,所以其他庫依舊動(dòng)態(tài)鏈接,所以在一個(gè)程序中,鏈接并非只有一種。文章來源地址http://www.zghlxwxcb.cn/news/detail-725068.html

到了這里,關(guān)于系統(tǒng)文件IO、文件描述符fd、重定向、文件系統(tǒng)、動(dòng)態(tài)庫和靜態(tài)庫的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(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】基礎(chǔ)IO(一) :文件描述符,文件流指針,重定向

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

    ?? 作者: 阿潤菜菜 ?? 專欄: Linux系統(tǒng)編程 是不是只有C/C++有文件操作呢?python、java、go等文件接口操作的方法是不太一樣的,那如何理解這種現(xiàn)象?有沒有統(tǒng)一的視角去看待所有的語言文件操作呢?—我們今天從系統(tǒng)視角去理解 ---- 實(shí)際都是通過系統(tǒng)調(diào)用來訪問 文件=內(nèi)

    2024年01月18日
    瀏覽(25)
  • 【Linux】基礎(chǔ)IO_文件描述符與重定向

    【Linux】基礎(chǔ)IO_文件描述符與重定向

    環(huán)境:centos7.6,騰訊云服務(wù)器 Linux文章都放在了專欄:【 Linux 】歡迎支持訂閱 相關(guān)文章推薦: 【Linux】馮.諾依曼體系結(jié)構(gòu)與操作系統(tǒng) 【C/進(jìn)階】如何對(duì)文件進(jìn)行讀寫(含二進(jìn)制)操作? 【Linux】基礎(chǔ)IO_文件操作 在前文中學(xué)習(xí)了open函數(shù),我們知道 open函數(shù)的返回值就是文件描

    2024年02月03日
    瀏覽(20)
  • 【探索Linux】—— 強(qiáng)大的命令行工具 P.13(文件系統(tǒng) | 軟硬鏈接 | 動(dòng)態(tài)庫和靜態(tài)庫)

    【探索Linux】—— 強(qiáng)大的命令行工具 P.13(文件系統(tǒng) | 軟硬鏈接 | 動(dòng)態(tài)庫和靜態(tài)庫)

    在計(jì)算機(jī)科學(xué)領(lǐng)域中,Linux 系統(tǒng)一直以來都是備受推崇的操作系統(tǒng)之一。其中,文件系統(tǒng)、軟硬鏈接、動(dòng)態(tài)庫和靜態(tài)庫是 Linux 系統(tǒng)中非常重要的概念,在實(shí)際應(yīng)用中扮演著不可或缺的角色。 在上一篇文章中,我們了解了 Linux 系統(tǒng)中文件描述符、重定向以及基礎(chǔ) IO 操作的相關(guān)

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

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

    前面我們講了C語言的基礎(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語言的基礎(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學(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】文件描述符 - fd

    【Linux】文件描述符 - fd

    使用 man open 指令查看手冊(cè): open 函數(shù)具體使用哪個(gè),和具體應(yīng)用場景有關(guān)。如:目標(biāo)文件不存在,需要 open 創(chuàng)建,則第三個(gè)參數(shù)表示創(chuàng)建文件的默認(rèn)權(quán)限;否則使用兩個(gè)參數(shù)的 open。 write read close lseek ,類比 C 文件相關(guān)接口。 操作文件,除了使用 C 語言的接口【Linux】回顧

    2024年03月23日
    瀏覽(24)
  • Linux--文件描述符fd的本質(zhì)

    Linux--文件描述符fd的本質(zhì)

    ?? ?

    2024年02月16日
    瀏覽(21)
  • Linux - fd文件描述符和文件詳解

    Linux - fd文件描述符和文件詳解

    ? ???????????????????????????????????????????????????????? ? ? ? ? ? ????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???感謝各位 點(diǎn)贊 收藏 評(píng)論 三連支持 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 本文

    2024年02月08日
    瀏覽(20)
  • 【Linux系統(tǒng)編程】Linux下的編譯器——gcc/g++的使用 及 動(dòng)態(tài)庫和靜態(tài)庫的認(rèn)識(shí)

    【Linux系統(tǒng)編程】Linux下的編譯器——gcc/g++的使用 及 動(dòng)態(tài)庫和靜態(tài)庫的認(rèn)識(shí)

    這篇文章我們繼續(xù)學(xué)習(xí)Linux中的開發(fā)工具,今天要學(xué)的是: Linux下的編譯器——gcc/g++ 我們先來簡單了解一下它們的概念: gcc (GNU Compiler Collection) 和 g++ 是 Linux 系統(tǒng)上最常用的編譯器。它們是 GNU 組織開發(fā)的一套開源編譯器工具集。 gcc: gcc 是 GNU 編譯器集合中的 C 語言編譯器。

    2024年02月16日
    瀏覽(23)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包