Linux系統應用程式設計 檔案IO

2021-09-16 12:08:14 字數 4157 閱讀 1370

檔案描述符

files_struct *file結構體記錄在task_struct結構體中,*file指向檔案描述符。

乙個程序預設開啟三個檔案描述符

stdin_fileno 0

stdout_fileno 1

stderr_fileno 2

新開啟檔案返回檔案描述符表中未使用的最小檔案描述符

open函式開啟檔案,open原型如下:

int open(const char * pathname, int flags);

int open(const char * pathname, int flags, mode_t mode);

* o_rdonly 唯讀開啟

* o_wronly 只寫開啟

* o_rdwr 可讀可寫開啟

以下可選項可以同時指定0個或多個,和必選項按位或起來作為flags引數。可選項有很多,這裡只介紹一部分,其它選項可參考open(2)的man page:

而不覆蓋原來的內容。

* o_creat 若此檔案不存在則建立它。使用此選項時需要提供第三個引數mode,表示該

檔案的訪問許可權。

* o_excl 如果同時指定了o_creat,並且檔案已存在,則出錯返回。

* o_trunc 如果檔案已存在,並且以只寫或可讀可寫方式開啟,則將其長度截斷(truncate)為0位元組。

* o_nonblock 對於裝置檔案,以o_nonblock方式開啟可以做非阻塞i/o(nonblock i/o)

關閉檔案用close函式,close函式原型如下:

int close (int fd);
close返回值,關閉成功返回0,錯誤返回-1.

read函式從開啟的裝置或檔案中讀取資料

ssize_t read(int fd, void *buf, size_t count)
write函式向開啟的裝置或檔案中寫資料

ssize_t write(int fd, const void *buf, size_t count);
返回值:成功返回寫入的位元組數,出錯返回-1並設定errno

下面使用檔案io來實現乙個cp命令類似的功能

#include #include #include #include #include #include #include #define size 8192

int main(int argc, char * ar**)

fd_src = open(ar**[1], o_rdonly);

fd_dest = open(ar**[2], o_creat | o_wronly | o_trunc, 0777);

/**成功返回讀到的位元組數

*讀到檔案末尾返回0

*讀失敗返回-1

*/while((len = read(fd_src, buf, sizeof(buf))) >0 )

write(fd_dest, buf, len);

close(fd_src);

close(fd_dest);

return 0;

}

執行結果如下:

可以看到拷貝的2.txt與1..txt檔案一樣

lseek可移動當前檔案讀寫位置,函式原型:

off_t lseek (int fd, off_t offset, int whence)
seek_set       表從檔案的起始位置偏移offset大小的位元組

seek_cur     表從當前位置加上offset大小的位元組

seek_end     表從未見末尾加上offset大小的位元組

lseek返回值:當lseek成功完成時,lseek()返回的偏移量是距離檔案開頭的偏移量,大小是以自己為單位衡量。如果錯誤返回值為-1,並設定errno的值

例1:用lseek拓展乙個檔案,注意一定要有一次寫操作

#include #include #include #include #include #include #include int main(void)

//拓展乙個檔案,一定要有一次寫操作

lseek(fd, 0x1000, seek_set);

//write(fd, "a", 1);

close(fd);

return 0;

}

注釋後://write(fd, "a", 1);

去掉注釋

例2:用lseek輸出乙個檔案的大小

#include #include #include #include #include #include #include int main(void)

fd = open("hello", o_rdwr);

if(fd < 0)

file_size = lseek(fd, 0, seek_end);

printf("hello size = %d.\n", file_size);

close (fd);

return 0;

}

執行結果

四、設定/獲取檔案控制屬性

fcntl函式原型如下:

#include #include int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);

int fcntl(int fd, int cmd, struct flock *lock);

先看乙個例程,這裡重新開啟stdin_fileno,並新增非阻塞的屬性,當使用者有輸入時,直接在標準輸出上顯示使用者的輸入,實現類似cat的功能(只不過這裡是非阻塞)

#include #include #include #include #include #include #include #include #include #include #define msg_try "try again\n"

int main(void)

tryagain:

n = read(fd, buf, 10);

if(n < 0)

perror("read /dev/tty");

exit(1);

}write(stdout_fileno, buf, n);

close(fd);

return 0;

}

為什麼我們不直接對

stdin_fileno

做非阻塞

read

,而要重新

open

一遍/dev/tty

呢?因為

stdin_fileno

在程式啟動時已經被自動開啟了,而我們需要在呼叫

open

時指定o_nonblock

標誌。

這裡用fcntl函式改變乙個已開啟的檔案的屬性,可以重新設定讀、寫、追加、非阻塞等標誌(這些標誌稱為file status flag),而不必重新open檔案。

所以上面的**可修改如下,用fcntl函式實現

#include #include #include #include #include #define msg_try "try again\n"

int main(void)

tryagain:

n = read(stdin_fileno, buf, 10);

if (n < 0)

perror("read stdin");

exit(1);

} write(stdout_fileno, buf, n);

return 0;

}

Linux串列埠應用程式設計

常見的資料通訊的基本方式可分為並行通訊與序列通訊兩種。1.並行通訊是指利用多條資料傳輸線將乙個字資料的各位元位同時傳送。它的特點是傳輸速度快,適用於傳輸距離短且傳輸速度較高的通訊。2.序列通訊是指利用一條傳輸線將資料以位元位為單位順序傳送。特點是通訊 線路簡單,利用簡單的線纜就可實現通訊,降低成本,...

Linux應用程式設計 mmap

二話不說,上來就問下那個man name mmap,munmap map or unmap files or devices into memory synopsis include void mmap void addr,size t length,int prot,int flags,int f...

IAP 應用程式設計

1 檢查是否需要對第二部分 進行更新 2 如果不需要更新則轉到4 3 執行更新操作 4 跳轉到第二部分 執行 第一部分 必須通過其它手段,如jtag或isp燒入 第二部分 可以使用第一部分 iap功能燒入,也可以和第一部分 一道燒入,以後需要程式更新是再通過第一部分iap 更新。對於stm32來說,...