日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux的文件 I/O操作

發(fā)布時間:2025/3/15 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux的文件 I/O操作 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Linux下的文件類型簡述


1、文件分類

1、linux 中對目錄和設備的操作都是文件操作, 文件分為普通文件, 目錄文件, 鏈接文件和設備文件。
2、普通文件: 也稱磁盤文件, 并且能夠進行隨機的數(shù)據(jù)存儲(能夠自由 seek
定位到某一個位置);
3、管道: 是一個從一端發(fā)送數(shù)據(jù), 另一端接收數(shù)據(jù)的數(shù)據(jù)通道;
4、目錄: 也稱為目錄文件, 它包含了保存在目錄中文件列表的簡單文件。
5、設備: 該類型的文件提供了大多數(shù)物理設備的接口。 它又分為兩種類型:字符型設備和塊設備。 字符型設備一次只能讀出和寫入一個字節(jié)的數(shù)據(jù),包括調(diào)制解調(diào)器、 終端、 打印機、 聲卡以及鼠標; 塊設備必須以一定大小的塊來讀出或者寫入數(shù)據(jù), 塊設備包括 CD-ROM、 RAM 驅(qū)動器和磁盤驅(qū)動器等, 一般而言, 字符設備用于傳輸數(shù)據(jù), 塊設備用于存儲數(shù)據(jù)。
6、鏈接: 類似于 Windows 的快捷方式和 Linux 里的別名, 指包含到達另一個文件路徑的文件。
7、套接字: 在 Linux 中,套接字也可以當作文件來進行處理。

2、標準 I/O 文件操作(基于文件指針帶有緩沖區(qū)的)

**1. 文件的創(chuàng)建, 打開與關閉**#include <stdio.h> //頭文件包含 FILE *fopen(const char *path,const char *mode); //文件名 模式 int fclose(FILE *stream);fopen 以 mode 的方式打開或創(chuàng)建文件, 如果成功, 將返回一個文件指針, 失敗則返回 NULL. fopen 創(chuàng)建的文件的訪問權限將以 0666 與當前的 umask 結合來確定。

Linux 系統(tǒng)中,mode 里面的’b’(二進制)可以去掉, 但是為了保持與其他系統(tǒng)的兼容性, 建議不要去掉。
ab 和 a+b 為追加模式,這兩種模式寫數(shù)據(jù)時都將是在文件末尾添加, 所以比較適合于多進程寫同一個文件的情況下保證數(shù)據(jù)的完整性。
2. 讀寫文件

數(shù)據(jù)塊讀寫:


#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);

fread 從文件流 stream 中讀取 nmemb 個元素, 寫到 ptr 指向的內(nèi)存中, 每個元素的大小為 size 個字節(jié)。
fwrite 從 ptr 指向的內(nèi)存中讀取 nmemb 個元素, 寫到文件流 stream 中, 每個元素 size 個字節(jié)。所有的文件讀寫函數(shù)都從文件的當前讀寫點開始讀寫, 讀寫完以后, 當前讀寫點自動往后移動size*nmemb 個字節(jié)。
整塊 copy, 速度較快, 但是是二進制操作。

格式化讀寫


printfscanfint fprintf(FILE *stream, const char *format, ...); 重點 sprintf(buf,”the string is;%s”,str); 重點 int sscanf(char *str, const char *format, …); 重點fprintf 將格式化后的字符串寫入到文件流 stream 中 sprintf 將格式化后的字符串寫入到字符串 str 中

單個字符讀寫

#include <stdio.h> int fgetc(FILE *stream); int fputc(int c, FILE *stream); int getc(FILE *stream); ? 等同于 fgetc(FILE* stream) int putc(int c, FILE *stream); ? 等同于 fputc(int c, FILE* stream) int getchar(void); ? 等同于 fgetc(stdin); int putchar(int c); ? 等同于 fputc(int c, stdout);

字符串讀寫:

char *fgets(char *s, int size, FILE *stream); int fputs(const char *s, FILE *stream); int puts(const char *s); ? 等同于 fputs(const char *s,stdout); char *gets(char *s); ? 等同于 fgets(const char *s, int size, stdin);

文件定位:
文件定位指讀取或設置文件當前讀寫點, 所有的通過文件指針讀寫數(shù)據(jù)的
函數(shù), 都是從文件的當前讀寫點讀寫數(shù)據(jù)的。

#include <stdio.h> int feof(FILE * stream); //通常的用法為 while(!feof(fp)) int fseek(FILE *stream, long offset, int whence);//設置當前讀寫點到偏移 whence 長度為 offset 處 long ftell(FILE *stream); //用來獲得文件流當前的讀寫位置 void rewind(FILE *stream); //把文件流的讀寫位置移至文件開頭 ?fseek(fp, 0, SEEK_SET); feof 判斷是否到達文件末尾的下一個( 注意到達文件末尾之后還會做一次) fseek 設置當前讀寫點到偏移 whence 長度為 offset 處, whence 可以是: SEEK_SET (文件開頭 ?0) SEEK_CUR (文件當前位置 ?1) SEEK_END (文件末尾 ?2) ftell 獲取當前的讀寫點 rewind 將文件當前讀寫點移動到文件頭

3. 目錄相關操作


改變目錄或文件的訪問權限#include <sys/stat.h> int chmod(const char* path, mode_t mode);//mode 形如: 0777 path 參數(shù)指定的文件被修改為具有 mode 參數(shù)給出的訪問權限。獲取、 改變當前目錄:#include <unistd.h> //頭文件 char *getcwd(char *buf, size_t size); //獲取當前目錄, 相當于 pwd 命令 int chdir(const char *path); //修改當前目錄, 即切換目錄, 相當于 cd 命令getcwd()函數(shù),倘若參數(shù) buf 為 NULL, getcwd()會依 參數(shù) size 的大小自動配置內(nèi)存(使用 malloc()), 如果參數(shù) size 也為 0, 則 getcwd()會依工作目錄絕對路徑的字符串程度來決定所配置的內(nèi)存大小 chdir()函數(shù): 用來將當前的工作目錄改變成以參數(shù) path 所指的目錄創(chuàng)建和刪除目錄: #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> int mkdir(const char *pathname, mode_t mode); //創(chuàng)建目錄,mode 是目錄權限 int rmdir(const char *pathname); //刪除目錄 也可用#include <unistd.h> int unlink(const char *pathname); 來刪除硬連接數(shù)獲取目錄信息#include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); //打開一個目錄 struct dirent *readdir(DIR *dir); //讀取目錄的一項信息, 并返回該項信息的結構體指針 void rewinddir(DIR *dir); //重新定位到目錄文件的頭部 void seekdir(DIR *dir,off_t offset);//用來設置目錄流目前的讀取位置 off_t telldir(DIR *dir); //返回目錄流當前的讀取位置 int closedir(DIR *dir); //關閉目錄文件#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat(const char *pathname, struct stat *buf); 獲取文件狀態(tài)讀取目錄信息的步驟為:1. 用 opendir 函數(shù)打開目錄;2. 使用 readdir 函數(shù)迭代讀取目錄的內(nèi)容, 如果已經(jīng)讀取到目錄末尾, 又想重新開始讀, 則可以使用 rewinddir 函數(shù)將文件指針重新定位到目錄文件的起始位置;3. 用 closedir 函數(shù)關閉目錄1、opendir()用來打開參數(shù) name 指定的目錄, 并返回 DIR*形態(tài)的目錄流 2、readdir()函數(shù)用來讀取目錄的信息, 并返回一個結構體指針, 該指針保存了目錄的相關信息。 有錯誤發(fā)生或者讀取到目錄文件尾則返回 NULL; 3、seekdir()函數(shù)用來設置目錄流目前的讀取位置, 再調(diào)用 readdir()函數(shù)時, 便可以從此新位置開始讀取。 參數(shù) offset 代表距離目錄文件開頭的偏移量。 4、telldir()函數(shù)用來返回目錄流當前的讀取位置。接下來看一下相關結構體的內(nèi)容: 1、目錄信息結構體: struct dirent {ino_t d_ino; /* inode number( 此目錄進入點的 inode) */off_t d_off; /* offset to the next dirent( 目錄開頭到進入點的位移 */unsigned short d_reclen; /* length of this record( 目錄名的長度) */unsigned char d_type; /* type of file( 所指的文件類型) */char d_name[256]; /* filename( 文件名) */ }; 2、文件狀態(tài)及相關信息結構體: struct stat {dev_t st_dev; /*如果是設備, 返回設備表述符, 否則為 0*/ino_t st_ino; /* i 節(jié)點號 */mode_t st_mode; /* 文件類型 */nlink_t st_nlink; /* 鏈接數(shù) */uid_t st_uid; /* 屬主 ID */gid_t st_gid; /* 組 ID */dev_t st_rdev; /* 設備類型*/off_t st_size; /* 文件大小, 字節(jié)表示 */blksize_t st_blksize; /* 塊大小*/blkcnt_t st_blocks; /* 塊數(shù) */time_t st_atime; /* 最后訪問時間*/time_t st_mtime; /* 最后修改時間*/time_t st_ctime; /* 最后權限修改時間 */ };接下來舉一個實例: 以樹形結構的形式輸出指定目錄下面的所有文件 #include <unistd.h> #include <stdio.h> #include <dirent.h> #include <string.h> #include <sys/stat.h> #include <stdlib.h> void printdir(char *dir, int depth) {DIR *dp = opendir(dir);if(NULL == dp){fprintf(stderr,"cannot open directory: %s\n", dir);return;} chdir(dir);struct dirent *entry;struct stat statbuf;while((entry = readdir(dp)) != NULL){stat(entry->d_name,&statbuf);if(S_ISDIR(statbuf.st_mode)){if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0)continue;printf("%*s%s/\n",depth,"",entry->d_name);printdir(entry->d_name,depth+4);}elseprintf("%*s%s\n",depth,"",entry->d_name);//printf(“%*s” ,4,” *” ); 該函數(shù)表示輸出“___*” ,前面輸出 3 個空格。//如果是 printf(“%*s” ,4,“**” );則表示輸出“__**” , 前面輸出 2 個空格。} chdir("..");closedir(dp); }int main(int argc, char* argv[]) {char *topdir, pwd[2]=".";if (argc < 2)topdir=pwd;elsetopdir=argv[1];printf("Directory scan of %s\n",topdir);printdir(topdir,0);printf("done.\n");exit(0); }

4、標準輸入/輸出流


在進程一開始運行, 就自動打開了三個對應設備的文件, 它們是標準輸入、 輸出、 錯誤流, 分別用全局文件指針 stdin、 stdout、 stderr 表示, stdin 具有可讀屬性, 缺省情況下是指從鍵盤的讀取輸入, stdout 和 stderr 具有可寫屬性, 缺省情況下是指向屏幕輸出數(shù)據(jù)。
示例:

#include <stdio.h> #include <unistd.h> int main() {char szBuf[32];printf("Input string:"); //向屏幕輸出一字符串fgets(szBuf,sizeof(szBuf),stdin);//從鍵盤讀入一行字符串fprintf(stdout,"The string is:%s",szBuf);//向屏幕輸出一行字符串return 0; }

3、基于文件描述符的文件操作(非緩沖)

1、文件描述符簡述
內(nèi)核為每個進程維護一個已打開文件的記錄表, 文件描述符是一個較小的正整數(shù)( 0—1023) , 它代表記錄表的一項, 通過文件描述符和一組基于文件描述符的文件操作函數(shù), 就可以實現(xiàn)對文件的讀、 寫、 創(chuàng)建、 刪除等操作。 常用基于文件描述符的函數(shù)有 open( 打開) 、 creat( 創(chuàng)建) 、 close( 關閉) 、 read( 讀取) 、 write( 寫入) 、 ftruncate( 改變文件大小) 、 lseek( 定位) 、 fsync( 同步) 、 fstat( 獲取文件狀態(tài)) 、 fchmod( 權限) 、 flock( 加鎖) 、 fcntl( 控制文件屬性) 、
dup( 復制) 、 dup2、 select 和 ioctl。 基于文件描述符的文件操作并非 ANSI C 的函數(shù)。

:如果不清楚某個函數(shù)的具體實現(xiàn)形式, 可以通過下面的方式查詢
man 函數(shù)名 查看該函數(shù)的幫助。

2、操作函數(shù)

**打開、 創(chuàng)建和關閉文件** open 和 creat 都能打開和創(chuàng)建函數(shù), 原型為#include <sys/types.h> //頭文件 #include <sys/stat.h> #include <fcntl.h>int open(const char *pathname, int flags); //文件名 打開方式 int open(const char *pathname, int flags, mode_t mode);//文件名 打開方式 權限 int creat(const char *pathname, mode_t mode); //文件名 權限 //現(xiàn)在已經(jīng)不常用了 creat 函數(shù)等價于?open(pathname,O_CREAT|O_TRUNC|O_WRONLY,mode);open()函數(shù)出錯時返回-1, 相關參數(shù)如下:flags 和 mode 都是一組掩碼的合成值, flags 表示打開或創(chuàng)建的方式, mode 表示文件的訪問權限。close 用于文件的關閉: int close(int fd);//fd 表示文件描述詞,是先前由 open 或 creat 創(chuàng)建文件時的返回值。文件使用完畢后, 應該調(diào)用 close 關閉它, **一旦調(diào)用close, 則該進程對文件所加的鎖全都被釋放,并且使文件的打開引用計數(shù)減 1, 只有文件的打開引用計數(shù)變?yōu)?0 以后, 文件才會被真正的關閉。**

注:
LINUX 中基于文件描述符的 open 函數(shù), 對于一個不存在的文件, 不能通過 O_WRONLY 的方式打開, 必須加上 O_CREAT 選項。

**讀寫文件、改變文件大小、文件定位、獲取文件信息、以及文件描述符的復制** 1、讀寫文件#include <unistd.h> ssize_t read(int fd, void *buf, size_t count);//文件描述詞 緩沖區(qū) 長度 ssize_t write(int fd, const void *buf, size_t count); 對于 readwrite 函數(shù), 出錯返回-1, 讀取完了之后, 返回 0, 其他情況返回讀寫的個數(shù)。2、改變文件大小#include <unistd.h> int ftruncate(int fd, off_t length); 函數(shù) ftruncate 會將參數(shù) fd 指定的文件大小改為參數(shù) length 指定的大小。 參數(shù) fd 必須為為已經(jīng)打開的文件描述詞, 而且必須是以寫入模式打開的文件。 如果原來的文件大小比參數(shù) length 大, 則超過的部分會被刪去。 返回值 執(zhí)行成功則返回 0, 失敗返回-13、文件定位函數(shù) lseek 將文件指針設定到相對于 whence, 偏移值為 offset 的位置 #include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence);//fd 文件描述詞whence 可以是下面三個常量的一個SEEK_SET 從文件頭開始計算SEEK_CUR 從當前指針開始計算SEEK_END 從文件尾開始計算利用該函數(shù)可以實現(xiàn)文件空洞( 對一個新建的空文件, 可以定位到偏移文件開頭 1024 個字節(jié)的地方, 在寫入一個字符, 則相當于給該文件分配了 1025 個字節(jié)的空間, 形成文件空洞) 通常用于多進程間通信的時候的共享內(nèi)存。實例: int main() {int fd = open("c.txt", O_WRONLY | O_CREAT);lseek(fd, 1024, SEEK_SET);write(fd, "a", 1);close(fd);return 0; } **注:** 文件中的空洞并不需要在磁盤上分配磁盤塊,在偏移之后,在寫入一個數(shù)據(jù),即可實現(xiàn)空洞,并且,使用lseek函數(shù)的偏移量大于當前文件大小是允許的。 可用 od -c file 查看文件中的內(nèi)容,-c是以字符方式打開的。 可使用 ls -ls file.hole file.nohole 比較差別,第一個數(shù)據(jù)便是占用的磁盤塊。4、獲取文件信息可以通過 fstat 和 stat 函數(shù)獲取文件信息, 調(diào)用完畢后, 文件信息被填充到結構體 struct stat 變量中, 函數(shù)原型為: #include <sys/types.h> #include <sys/stat.h> #include <unistd.h>int stat(const char *file_name, struct stat *buf); //文件名 stat 結構體指針 int fstat(int fd, struct stat *buf); //文件描述詞 stat 結構體指針,關于結構體,上面已經(jīng)給出了。5、文件描述符的復制#include <unistd.h> //頭文件包含int dup(int oldfd); int dup2(int oldfd, int newfd);1、系統(tǒng)調(diào)用函數(shù)dup和dup2可以實現(xiàn)文件描述符的復制,經(jīng)常用來重定向進程的 stdin(0),stdout(1),stderr(2)。 2、dup 返回新的文件描述符(**沒有使用的文件描述符的最小編號**) 。 這個新的描述符是舊文件描述符的拷貝。**這意味著兩個描述符共享同一個數(shù)據(jù)結構。** 3、dup2 允許調(diào)用者用一個有效描述符(oldfd)和目標描述符(newfd), 函數(shù)成功返回時, 目標描述符將變成舊描述符的復制品, 此時兩個文件描述符現(xiàn)在都指向同一個文件, 并且是函數(shù)第一個參數(shù)( 也就是oldfd) 指向的文件。 4、文件描述符的復制是指用另外一個文件描述符指向同一個打開的文件, 它完全不同于直接給文件描述符變量賦值,若是賦值,兩個文件描述符變量的值相同, 指向同一個打開的文件, **但是內(nèi)核的文件打開引用計數(shù)還是為1**,所以 close掉任意一個都會導致文件立即關閉掉。 對于描述符的復制:內(nèi)核的文件打開引用計數(shù)便會加一,關閉任意一個,通過另一個照樣可以訪問文件,只有都關閉,文件才正式關閉。 5、這兩個接口常用來重定向,例如,進程默認的就打開了 0,1,2 表示標準輸入, 標準輸出, 標準錯誤輸出。此時在關閉一個,比如 close(1);則表示關閉標準輸出,當在調(diào)用fd2=dup(fd)時,當我們printf想要輸出時,實際上是向fd2對應的文件輸入內(nèi)容了。 6、其dup2的原理也是一樣的,eg:close(1);int fd1;printf("fd=%d\n",fd);//可以打印fd1=dup2(fd,STDOUT_FILENO);printf("fd1=%d\n",fd1);//這一句無法顯示到屏幕上puts("you can't see me");

3、標準輸入輸出文件描述符


與標準的輸入輸出流對應, 在更底層的實現(xiàn)是用標準輸入、 標準輸出、 標準錯誤文件描述符表示的。它們分別用 STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 三個宏表示, 值分別是 0、 1、 2

標準輸入文件描述符 ? STDIN_FILENO ? 0
標準輸出文件描述符 ? STDOUT_FILENO ? 1
標準錯誤輸出文件描述符 ? STDERR_FILENO ? 2

4、I/O 多路轉(zhuǎn)接模型

在這種模型下, 如果請求的 I/O 操作阻塞, 且它不是真正阻塞 I/O,而是讓其中的一個函數(shù)等待, 在這期間, I/O 還能進行其他操作。

5、文件共享時,一個進程內(nèi)核為其維護的數(shù)據(jù)結構圖—3張表

linux并沒有采用v節(jié)點而是才用的是與文件相關的i節(jié)點,與文件無關的i節(jié)點

dup之后的內(nèi)核數(shù)據(jù)結構

總結

以上是生活随笔為你收集整理的linux的文件 I/O操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲国产成人无码av在线 | 蜜桃做爰免费网站 | 男人靠女人免费视频网站 | 久久久久久久久国产 | 张柏芝亚洲一区二区三区 | 成人v精品蜜桃久一区 | 伊人成人久久 | 久久国产精品久久精品国产 | 先锋资源网av | 美女极度色诱图片www视频 | 色小说在线 | 啪啪在线视频 | 欧美一区二区三区成人久久片 | 中文字幕观看 | 色呦呦官网 | 亚洲综合另类小说 | 中文字幕久久久久 | 中文字幕亚洲精品在线 | 性色在线视频 | 中文字幕在线观看视频一区二区 | 精品国产青草久久久久96 | 天天爽夜夜春 | 免费看黄网址 | 男女性杂交内射妇女bbwxz | 国产精品美女高潮无套 | 人妻夜夜爽天天爽 | 91麻豆精品在线 | 18成人免费观看网站 | 日本中文字幕网站 | 午夜亚洲AV永久无码精品蜜芽 | 91精品国产自产精品男人的天堂 | 久久中文字幕视频 | 日日夜夜伊人 | 色版视频 | 印度午夜性春猛xxx交 | k8yy毛片 | 免费的av片 | 日韩精品一区二区三区国语自制 | 国产精品福利电影 | 日本视频在线免费观看 | 欧美另类一区二区 | 国产私密视频 | 欧美日韩激情在线观看 | 伊是香蕉大人久久 | h网址在线观看 | 中文字幕免费高清 | 青青草原伊人 | 国产精品午夜在线观看 | 欧美在线天堂 | 国产精品成人va在线观看 | 波多野结衣在线观看视频 | 女女百合高h喷汁呻吟玩具 www.亚洲一区 | 动漫av一区二区 | 国产亚洲精品久久久久久青梅 | 国产精品二区三区 | 欧美高清| 蜜桃臀aⅴ精品一区二区三区 | 亚洲av无码国产在丝袜线观看 | 91久久久久国产一区二区 | 国产综合一区二区 | 色无极亚洲影院 | 欧美午夜精品久久久久久浪潮 | 欧美视频三区 | 日韩一区二区三区四区五区六区 | 成人免费在线看片 | 国产高清www| 99精品视频在线 | a在线天堂| 国产在线观看无码免费视频 | 国产成人自拍偷拍 | cao在线视频 | 97超碰在线资源 | 麻豆综合 | 91视频这里只有精品 | 日本三级大全 | 性视频欧美 | 色啪视频 | 欧美特级黄 | 日本一区二区不卡在线 | 男女啪啪在线观看 | 永久免费,视频 | 久久国产精品免费视频 | www.涩涩爱| 久久92| 99色婷婷 | 日本少妇aaa | 在线看a级片 | 毛片无码免费无码播放 | 欧美成人日韩 | 俄罗斯porn | 91综合精品 | 亚洲国产欧美一区 | 欧美大片在线看免费观看 | 日本精品久久久久 | 国产成人自拍偷拍 | 91国产在线看 | 在线国产视频一区 | 91视频播放器 | 少妇精品久久久一区二区三区 |