1. 程式人生 > >Linux基礎IO--檔案描述符fd/重定向

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。