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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux C高级编程——文件操作之系统调用

發布時間:2023/12/20 linux 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux C高级编程——文件操作之系统调用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux C高級編程文件操作之系統調用


宗旨:技術的學習是有限的,分享的精神是無限的!


?

? ? ? ? 庫函數是一些完成特定功能的函數,一般由某個標準組織制作發布,并形成一定的標準。使用庫函數編寫的函數一般可以應用于不同的平臺而不需要做任何修改,具有很好的可移植性。

? ? ? ? 系統調用函數與操作系統直接相關,不同的操作系統所使用的系統調用可能不太一樣,因此,如果兩個操作系統差異很大,系統調用函數的可移植性就不高。例如windows采用的系統調用的應用程序不能直接在Linux下編譯運行。

? ? ? ? 之所以使用系統調用是因為系統資源的有限性以及內核管理的方便,系統調用將上層內的應用開發與底層的硬件實現分開,上層應用不需要關注底層硬件的具體實現。Linux的系統調用使用軟中斷實現,使用系統調用后,該程序的狀態將從用戶態切換到內核態。庫函數實現最終也要調用系統調用函數,但它封裝了系統調用操作,從而增加了代碼的可移植性。

?

1open()函數

——用于打開或者創建一個文件

(1)函數原型:

#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> int open(constchar* pathname, int flags, ...)

(2)參數

pathname:要創建或者打開的文件名

flags: 指定文件的打開模式、標志等信息

必須指定一個:O_RDONLY ——只讀?? O_WRONLY——只寫 O_RDWR——讀寫

可選標志(按位或):O_APPEND——追加

O_TRUNC——若文件存在,讀寫方式打開或只寫打開,則文件長度為0

O_CREAT——若文件不存在,則創建文件,此時,open需要第三個參數,用于指定該? 文件的訪問權限(umask可以看掩碼)

O_EXCL——若同時指定為O_CREAT標志,而文件已經存在,則會出錯,可用于文件? 是否存在

O_NONBLOCK對于設備文件,以O_NONBLOCK方式打開可以做非阻塞I/O

(3)返回值

整數類型——成功時,返回文件描述符;出錯時,返回-1?

(4)文件描述符

(文件描述符——已打開文件的索引——通過索引找到已打開文件)

文件描述符是一個非負的整數

文件描述符0,1,2分別表示標準輸入,標準輸出,標準錯誤輸出,在進程創建時,已經打開。open返回的文件描述符一定是該進程尚未使用的最小描述符?

(5)出錯處理

errno.h頭文件中,定義了errno,當API調用出錯時,errno說明出錯的具體原因

可簡單的將errno理解成整型數據

出錯信息轉換成可讀字符串

#include<string.h>

char* strerror(int errno);

perror函數根據當前的errno,輸出一條出錯信息(void perror(constchar* msg))

#include<stdio.h> #include<stdlib.h>#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h>int main(int argc, char *argv[]) {int fd;if(argc < 2){puts("please input the open filepathname!\n");exit(1);}//如果flag參數里有O_CREAT表示,該文件如果不存在,系統則會創建該文件,該文 件的權限由第三個參數決定,此處為0755//如果flah參數里沒有O_CREAT參數,則第三個參數不起作用.此時,如果要打開的 文件不存在,則會報錯.//所以fd=open(argv[1],O_RDWR),僅僅只是打開指定文件if((fd = open(argv[1], O_CREAT | O_RDWR, 0755)) < 0){perror("open filefailure!\n");exit(1);}else{printf("open file %d success!\n", fd);}close(fd);return 0; }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>

2 creat()函數

——用于創建一個新文件

(1)函數原型

int creat(const char *pathname,mode_t mode)

(2)參數

pathname:要創建的文件名(包括路徑信息)

mode:同open的第二個參數,討論文件的訪問權限位時分析:

S_IRUSR——可讀?????? S_IWUSR——可寫????? S_IXUSR——可執行?? ? S_IRWXU——可讀、寫、執行

除了用上述宏之外,還可以用數字來表示文件的權限:

可讀——4? 可寫——2? 可執行——1? 無任何權限——0?

(3)返回值

成功返回只寫打開的文件描述符,出錯返回-1

(4)creat函數缺點:它以只寫方式打開創建的文件。若要創建一個臨時文件,并先寫該文件,然后又讀該文件,則必須先調用creat,close,然后再open.簡便方法:

open(pathname,O_RDWR| O_CREAT | O_TRUNC,mode);?

#include<stdio.h> #include<stdlib.h>#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h>void create_file(char *filename) {/*創建的文件具有什么樣的屬性?*/if(creat(filename, 0755) < 0){printf("create file %sfailure!\n", filename);exit(EXIT_FAILURE);}else{printf("create file %s success!\n", filename);} }int main(int argc, char *argv[]) {int i;if(argc < 2){perror("you haven't input thefilename,please try again!\n");exit(EXIT_FAILURE);}for(i = 1; i < argc; i++){create_file(argv[i]);}return 0; }?

3lseek函數(fseek類似)

——用于修改當前文件偏移量

(當前文件偏移量的作用:規定了從文件什么地方開始進行讀、寫操作)

——通常,讀寫操作結束時,會使文件偏移量增加讀寫的字節數

——當打開一個文件時,除非指定了O_APPEND標志,否則偏移量被設置為0

(1) 函數原型

#include<sys/types.h> #include<unistd.h> off_t lseek(int filedes, off_t offset, int whence)

(2) 參數

第一個參數filedes:open/creat函數返回的文件描述符

第二個參數offset:

相對偏移量:需結合whence才能計算出真正的偏移量

類型off_t:通常情況下是32為數據類型

第三個參數whence:該參數取值是三個常量

SEEK_SET:當前文件偏移量為——距文件開始出的offset個字節

SEEK_CUR:當前文件偏移量 + offset(可正可負)

SEEK_END:當前文件長度 + offset(可正可負)

(3)返回值:

成功返回新的文件偏移量,失敗返回-1

(4)獲取當前的偏移量:

Off_tcurrent_position;

Current_position= lseek(fd,0,SEEK_CUR);

lseek操作并不引起任何I/O操作,只是修改內核中的記錄(并不引起磁盤的訪問??? 操作)

(5)空洞文件

——使用lseek修改文件偏移量后,當前文件偏移量有可能大于文件的長度

——在這種情況下,對該文件的下一次寫操作,將加長該文件

——這樣文件中形成了一個空洞。對空洞區域進行讀,均返回0

?

4read函數

——用于從文件中讀出數據

(1)函數原型

#include<unistd.h> ssize_t read(int fd, void *buff, size_t nbytes)

(2)參數

第一個參數fd:文件描述符

第二個參數buff:指向緩沖區,用于存放從文件讀出的數據

第三個參數nbytes:unsigned int;需要從文件中讀出的字節數

——緩沖區的大小 >= nbytes?

(3)返回值

返回值類型:ssize_t,即int

出錯返回-1成功:返回從文件中實際讀到的字節數,當文件讀到結尾時,則返回0

(4)很多情況下,read實際讀出的字節數都小于要求讀出的字節數

——讀普通文件,在讀到要求的字節數之前,就到達了文件尾端

——當從終端設備讀時,通常一次最多讀一行

——當從網絡讀時,網絡中的緩沖機構可能造成read函數返回值小于所要求讀出????????? 的字節數

——某些面向記錄的設備,如磁盤,一次最多返回一個記錄?

#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h>#define LENGTH 100int main(void) {int fd, len;char str[LENGTH];/* 創建并打開文件 */fd = open("hello.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);if(fd)  {/* 寫入 Hello, software weekly字符串 */write(fd, "Hello,Software Weekly", strlen("Hello, software weekly"));close(fd);}fd = open("hello.txt", O_RDWR);len = read(fd, str, LENGTH);/* 讀取文件內容 */str[len] = '\0';printf("%s\n", str);close(fd);return 0; }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>

5write函數

——用于向文件里面寫入數據

(1) 函數原型

#include<unistd.h>

ssize_t write(int fd,const void*buff,size_t nbytes)

(2) 參數

第一個參數fd:文件描述符

第二個參數buff:指向緩沖區,存放了需要寫入文件的數據

第三個參數nbytes:需要寫入文件的字節數

(3) 返回值

返回值類型:ssize_t,即int

出錯返回-1,成功返回實際寫入文件的字節數

(4) write出錯的原因

——磁盤滿

——沒有訪問權限

——超過了給定進程的文件長度限制

?

6close函數

——用于關閉一個已打開的文件

(1)函數原型

int close(int filedes)

(2) 返回值

成功返回0,出錯返回-1

(3)參數

filedes:文件描述符

(4)當close函數關閉文件時,會釋放進程加在該文件上的所有記錄鎖

內核會對進程打開文件表,文件對象,索引節點表項等結構進行修改,釋放相關的?????? 資源

當進程退出時,會關閉當前所有已打開的文件描述符 ? ? ? ? ? ? ? ? ? ? ? ??

?

7ioctl函數

——用于向設備發控制和配置命令(這些數據不能用read/write讀寫)

(1) 函數原型

#include <sys/ioctl.h> int ioctl(int d, int request, ...)

(2) 參數

第一個參數d:某個設備的文件描述符

第二個參數request:是ioctl的命令,可變參數取決于request,通常是是一個指向? 變量或者結構體的指針

(3)返回值

若出錯返回-1,成功返回其他值,取決于request

ioctl(STDOUT_FILENO,TIOCGWINSZ,&size)——獲得終端設備的窗口大小

manioctl_list——可以看require的各種參數?

?

8mmap函數

——可以把磁盤文件的一部分直接映射到內存,這樣文件中的位置直接就有對應的內存地址,對文件的讀寫可以直接用指針來做而不需要read/write函數

(1) 函數原型

#include<sys/mman.h>

void* mmap(void *addr,size_t len,int prot,int flag,int filedes,off_t off)

(2) 參數

addr:NULL——內核會自己在進程地址空間中選擇合適的地址建立映射

len:需要映射的那部分文件的長度

off:從文件的什么位置開始映射,必須是頁大小的整數倍(32位——4K)

filedes:該文件的文件描述符

prot:

PROT_EXEC——映射的這一段可執行,例如映射的共享庫

PROT_READ——映射的這一段可讀

PROT_WRITE——映射的這一段可寫

PROT_NONE——映射的這一段不可訪問

flag:

MAP_SHARED——多個進程對同一文件的映射是共享的,一個進程對映射的內存做了修改,另一個進程也會看到這種變化。

MAP_PRIVATE——多個進程對同一文件的映射不是共享的,一個進程對映射的內存做了修改,另一個進程不會看到這種變化,也不會真的寫到文件中去。

(3)返回值

成功則返回映射的首地址,出錯返回常數MAP_FAILED。

?

9access函數

——判斷文件是否可以進行某種操作

(1)函數原型

int access(const char *pathname,int mode)

(2)參數

pathname:文件名

mode:判斷的訪問權限:R_OK:文件可讀? W_OK:文件可寫

?? X_OK:文件可執行? F_OK:文件存在

(3)返回值

成功時,返回0;如果一個條件不符合時,返回-1

?

10 dup函數

——復制文件描述符

(1) 函數原型

#include <unistd.h> int dup(int oldfd);

(2) 參數

oldfd:待復制的文件描述符

(3)返回值

成功返回新的文件描述符;失敗返回-1

?

11 dup2函數

——復制文件描述符

(1) 函數原型

#include <unistd.h> int dup2(int oldfd, int newfd);

(2) 參數

oldfd:待復制的文件描述符

newfd:新的文件描述符

(3) 返回值

成功返回新的文件描述符;失敗返回-1

?

//小項目:用系統調用函數實現文件拷貝的功能: /*************************************************************************> File Name: copy.c> Author: libang> Mail: 18211438613@163.com> Created Time: 2014年07月16日 星期三 00時15分12秒************************************************************************/#include<stdio.h> #include<string.h> #include<unistd.h> #include<sys/stat.h> #include<sys/types.h> #include<fcntl.h> #include<stdlib.h>int copy_file(intsrc_fd, int dest_fd);int main(intargc, char *argv[]) //注意先搭建主框架 {if(argc < 3){printf("inputerror!\n");exit(1);}int src_fd, dest_fd;src_fd = open(argv[1], O_RDONLY);dest_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);if(src_fd < 0 | dest_fd < 0){printf("file openfail!\n");exit(0);}copy_file(src_fd, dest_fd);printf("success!\n");close(src_fd);close(dest_fd);return 0; }int copy_file(intsrc, int dest) {char buf[128];int r_ret, w_ret;char *tmp;//memset(buf,0,128);printf("success!\n");while((r_ret = read(src, buf, 128)) > 0) //經典的拷貝算法{tmp = buf;while(r_ret){w_ret = write(dest, tmp, r_ret);r_ret = r_ret - w_ret;printf("%d\n", r_ret);tmp += w_ret;}//memset(buf,0,128);}printf("success!\n");return 0; }

總結

以上是生活随笔為你收集整理的Linux C高级编程——文件操作之系统调用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。