Linux基礎IO--檔案描述符fd/重定向
在學習檔案描述符之前,我們先來看一點其它相關的知識點。
我們都知道,對一個檔案我們可以進行開啟、讀、寫、關閉操作,在我們沒有接觸Linux之前,將資訊輸出到顯示器上,我們通常能想到的方法有以下幾種:
#include<stdio.h> #include<string.h> int main() { char *msg = "hello world!\n"; fwrite(msg, strlen(msg), 1, stdout); printf("hello world!\n"); fprintf(stdout, "hello world!\n"); return 0; }
C語言會預設幫我們開啟stdin、stdout、stderr這三個流,並且,這三個流的型別都是FILE*型的。
其實,上面三種方式,我們都是呼叫的C標準庫函式,但在Linux中也有這些操作,而它們都沒有帶“f”(例如open、read、write、close),這些實質上是系統呼叫介面,相當於被庫函式進行了一次封裝。
接下來,我們來總結一下“檔案描述符”的相關知識點!
一、檔案描述符
(1)概念
1.所謂檔案描述符,其實就是一個小整數;
2.Linux程序預設情況下會有3個預設開啟的檔案描述符,分別是標準輸入0,標準輸入1,準本錯誤2;
3.0,1,2,對應的物理裝置一般是:鍵盤、顯示器,輸入、輸出還可以採用如下方式;
1 #include<stdio.h> 2 #include<sys/types.h> 3 #include<sys/stat.h> 4 #include<fcntl.h> 5 #include<string.h> 6 7 int main() 8 { 9 char buf[1024]; 10 ssize_t s=read(0,buf,sizeof(buf)); 11 if(s>0){ 12 buf[s]=0; 13 write(1,buf,strlen(buf)); 14 write(2,buf,strlen(buf)); 15 } 16 return 0; 17 }
(2)相關圖
從這張圖,我們不難看出,檔案描述符就是從0開始的小整數。當我們開啟檔案時,作業系統在記憶體中要建立相應的資料結構來描述檔案,於是就有了file的結構體,此時已經開啟相應檔案物件。
而且從上圖不難看出,檔案描述符本質上就是陣列的下標,因此,只要拿著檔案描述符,就可以找到對應的檔案
(3)檔案描述符的分配規則
下面我們來看一段程式碼
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/stat.h>
4 #include<fcntl.h>
5
6 int main()
7 {
8 int fd=open("myfile",O_RDONLY);
9 if(fd<0){
10 perror("open");
11 return 1;
12 }
13 printf("fd:%d\n",fd);
14 return 0;
15 }
輸出結果:fd:3。這也就驗證了上面所說的一句話,作業系統會預設開啟0,1,2,三個檔案,存放stdin、stdout、stderror、當我們再開啟一個檔案時,它的檔案描述符會從3開始。
其實,除了這種情況以外,還有一種情況,當關閉了0、1、2三個檔案時,下一次當作業系統開啟一個新的檔案時,會預設從檔案描述符沒有使用的最小下標開始。(例如關閉了0,下一次開啟一個新的檔案時,該新檔案描述符為0),說到這裡,我們很容易產生一些疑問,這是怎麼回事,下面,我們再來看一個概念來解決我們的疑惑吧!
二、重定向
1.常見的重定向有:>(輸出重定向)、>>(追加重定向)、<(輸入重定向)
2.以輸出重定向為例,我們來看一段程式碼:
1 #include<stdio.h>
2 #include<sys/types.h>
3 #include<sys/stat.h>
4 #include<fcntl.h>
5 #include<stdlib.h>
6
7 int main()
8 {
9 close(1);
10 int fd=open("myfile",O_WRONLY|O_CREAT,0644);
11 if(fd<0){
12 preeor("open");
13 return 1;
14 }
15 printf("fd:%d\n",fd);
16 fflush(stdout);
17 close(fd);
18 exit(0);
19
20 }
我們會發現,本應該輸出到顯示器上面的內容,卻輸出到了檔案myfile當中,其中檔案myfile的fd為1,這就是所謂的輸出重定向。
3.重定向的本質
一般printf往stdout中輸出,但是stdout在底層訪問檔案的時候,找的還是fd=1,但此時fd:1下標所表示的內容,已經變成了myfile的地址,不再是顯示器檔案的地址,所以,輸出的任何訊息都會往檔案中寫入,進而完成輸出重定向。
通過上面的學習,我們都知道訪問檔案都是通過fd訪問的,因此C標準庫中的FILE結構體內部,必定封裝了fd。