Linux應用程式設計學習記錄(一)

2021-08-25 11:46:09 字數 3851 閱讀 3592

今天學習了讀寫檔案函式的相關知識,參考的書籍是周立功寫的《嵌入式linux開發教程(上冊)》,第11.3節。

1.  open函式和creat函式

因為creat函式可以用open函式來實現,所以就不再去理會它了。關於open函式,記憶起來可以拆解成幾點:

a)有int型返回值,返回的是所開啟檔案的控制代碼,或者稱為檔案描述符。

b)第乙個引數是字元型指標,用來傳遞所要開啟的檔名,通常的做法有兩種:可以建立乙個字元型陣列,將檔名存入陣列,再把陣列名當成第乙個引數;也可以直接把檔名字串當成第乙個引數。

c)第二個引數是限定以什麼方式開啟檔案,包括唯讀,只寫等等,具體配置的方法請檢視引數解釋。

d)第三個引數是當open函式用作建立新檔案時,設定檔案的許可權。引數如下:

之所以把這個**貼上出來,是為了說明我在寫測試程式時所遇到的問題:

看上去每個引數既可以寫符號常量,也可以寫對應的數值。但當我使用數值來指定檔案許可權時,發現建立的檔案許可權根本不對。經過反覆嘗試,最終發現不能使用數值,而要使用符號常量。我對此事的解釋是,寫教材的人所用的open函式可能與我的open函式在底層實現方法上有差異。那麼,相同的符號常量,對應的數值可能就變了。

通過這件事也給我乙個提醒,在調取這些標準庫函式時,引數盡量使用符號常量,不要圖省事寫數值。這可能導致程式的可移植性變差。

2.  關於檔案的許可權,再補充一些知識點:

a)linux對於新建檔案一般都有乙個預設的許可權,是由umask數值來決定的。umask在命令列中是一條指令,輸入就可以檢視系統的umask值。

b)umask的數值一般是4位的,比如我的系統查的umask值為0002。它怎麼理解呢?不看最左邊的那個0。剩下的002應該理解成 --- --- -w-

c)沒錯,umask就是檔案許可權的數字簡寫。最左邊三個字元代表檔案所屬使用者的操作許可權;中間三個字元代表與檔案所屬使用者在同乙個使用者組的其他使用者的操作許可權;最右邊三個字元代表其他使用者的操作許可權。

d)不過,umask所代表的許可權,指的是新建立檔案不應該具備的屬性。也就是說,雖然當前系統的umask數值翻譯過來是:只有其他使用者具備對檔案寫操作的許可權。但是新建的檔案,卻恰好要剝奪這個許可權。

e)更重要的是,umask對新檔案預設許可權的限制會與open函式建立新檔案時所指定的許可權共通決定新檔案的許可權。具體執行邏輯可以這樣理解:open函式指定新檔案的許可權,然後再根據umask的值砍掉其中的一些。

f)為了讓open函式可以完全指定新檔案的許可權,可以在程式中預先使用umask()函式指定umask的數值。

g)暫時不知道umask函式在哪個標頭檔案中宣告的,因此我在呼叫該函式時,編譯報警了,但不影響使用。

3.  關於write函式

關於write函式,記憶起來可以拆解成幾點:

a)有乙個有符號整型的返回值,代表實際寫入的字元數,如果出錯了則返回-1。

b)第乙個引數是檔案控制代碼(或者稱為檔案描述符),這與前面open函式的返回值是一回事。顯然,你要對乙個檔案進行寫操作,必須知道要操作的檔案是誰。而執行open函式的乙個效果,就是獲取開啟檔案的控制代碼。這個控制代碼拿來給write函式使用,邏輯上順理成章。

c)第二個引數是任意型別的資料指標,指向的是乙個緩衝區的首位址。這個緩衝區裡面預先放好打算寫入檔案的資料。也有兩種寫法,可以先建立乙個字元型數字,然後將陣列名用作引數;也可以直接把待寫入檔案的字串用作引數;這與open函式的第乙個引數用法類似。

d)第三個引數是無符號整型資料,代表的是將要寫入檔案的資料位元組數。

4.  使用write函式中遇到的問題

a)我建立了乙個名為text的字元型容量不限的陣列,並且給它賦值:text=」abc」;在填寫第三個引數時,使用sizeof函式。

用gedit檢視檔案,會提示有亂碼:

c)我認為多寫入檔案的那個字元是『\0』,因為系統會自動在字串的結尾加上『\0』作為結束標識。這個轉義字元也會占用乙個位元組,當使用sizeof函式來統計字串長度時,會把它也算在內。

d)為了驗證這個想法,我將write函式的第三個引數人為指定成3,這樣果然就一切正常了。

e)至於vi中顯示的那個^@符號,在網上查了下,有人指出它就是代表『\0』。

f)書中指出,實際寫入的字元數可以少於指定的字元數,我不太明白何時會出現這種情況?

隨便做了個小測試,將寫入的字元數人為指定成10個。執行程式後,用vi開啟file1.txt,看到這麼個東西:

看來,至少我這種嘗試並不會讓實際寫入文字的資料少於指定的值。這個問題懸而未決。。。。

5.  由乙個疑問引發的測試及其結果

用write函式寫入資料的時候,如果一次沒寫完,接下來想繼續寫怎麼辦?會不會把原先的內容覆蓋掉?換言之,作業系統怎麼知道從檔案的什麼地方開始寫資料?

a)我猜測,系統會有某種機制記憶寫入資料的起點。邏輯應該是,當第一次開啟檔案時,預設以最開頭的位置為起點。當寫過一次後,只要不關閉檔案,那麼下次再寫入會接著上次結束的位置繼續寫

b)為了驗證這想法,我先開啟檔案,然後寫入abc,緊接著又寫入def。完事後檢視檔案,果然就成了abcdef

c)再來乙個實驗,這次是先開啟檔案,然後寫入abc,關閉檔案。再開啟檔案,然後寫入def。完事後檢視檔案,果然就成了def。相當於覆蓋了abc

d)最後乙個實驗,先開啟檔案,然後寫入abc(使用第一次開啟檔案時獲得的控制代碼),不關閉檔案的情況下再用open開啟一次檔案,然後寫入def(使用第二次開啟檔案時獲得的控制代碼)。檢視檔案後,發現內容是def

e)這讓我突然對open函式連續開啟同乙個檔案產生了興趣。暫時沒有深入研究,只是做了兩個測試。

其一,開啟乙個檔案,然後不關閉再開啟一次。發現兩次的檔案控制代碼不同。

其二,開啟乙個檔案,關閉後再開啟,發現兩次檔案控制代碼相同。

這讓我感覺,控制代碼是臨時分配的。

6.  最後貼上今天寫的測試**

#include

#include

#include

#include

#include

#include //為了能執行printf函式所新增的標頭檔案

int main(int argc, char* argv)

res = write(fd, buf1, 3);

if (res < 0)

printf("write text into file failed!\n");

else

printf("write %d bytes into file1.txt\n",res);

close(fd);

/**************************第二次開啟檔案,並且寫入def,然後關閉*******************************/

fd1 = open("file1.txt", o_rdwr);

if (fd1 < 0)

printf("open file failed!\n");

else

res = write(fd1, buf2, 3);

if (res < 0)

printf("write text into file failed!\n");

else

printf("write %d bytes into file1.txt\n",res);

close(fd1);

return 0;

}

Linux應用程式設計學習記錄(二)

今天來繼續學習檔案操作的相關api。早上查了下資料,發現現在學的這些api隸屬於posix標準,posix翻譯過來就是可移植作業系統介面,在unix類系統中應用的十分廣泛。處理檔案的api還有很多別的標準,比如ansi c標準,它應該是標準c語言提供的庫函式。在別人的文章中看到,這二者比較起來的話,...

Linux應用程式設計學習記錄(三)

1.lseek函式 前兩次已經學過了write和read函式,這兩個函式在使用中可能存在對同乙個檔案多次操作的問題,因此不得不關注讀寫的起點是哪兒。假設有這麼乙個需求 乙個檔案中有6個字元,開啟檔案後我希望直接讀取第4個字元,這怎麼辦?顯然直接讀取是不行的了,你得移動讀寫起點。lseek函式就是為這...

Linux應用程式設計學習記錄(四)

今天開始學習關於程序的相關知識,參考的教材依然是周立功的 嵌入式linux開發教程 上冊 內容相當於第12章。因為沒多少機會寫 來體會,這部分內容可能會比較抽象,難以理解。總之乙個乙個來吧。初識程序 1.程序是乙個已經開始執行,但是還沒終止的程式例項。2.程序是乙個動態的實體,它是如何從靜態的程式轉...