Linux C編程第七章 系統(tǒng)IO函數(shù)2

      網(wǎng)友投稿 624 2025-03-31

      一、整體大綱

      二、 系統(tǒng)IO函數(shù)

      1. 一些概念

      文件描述符

      PCB

      C庫(kù)函的IO緩沖區(qū)

      1)?文件描述符

      int 類(lèi)型

      一個(gè)進(jìn)程最多可打開(kāi)多少文件

      2)?pcb

      進(jìn)程控制塊

      在其中有一個(gè)文件描述符表 -- 數(shù)組[1024]

      C庫(kù)IO函數(shù)工作流程:

      pcb和文件描述符:

      2. 虛擬地址空間

      虛擬地址空間就是程序啟動(dòng)起來(lái)之后從硬盤(pán)上會(huì)有一塊虛擬內(nèi)存分配出來(lái)。

      cpu 為什么要使用虛擬地址空間與物理地址空間映射?解決了什么樣的問(wèn)題?

      【Linux C編程】第七章 系統(tǒng)IO函數(shù)2

      1)方便編譯器和操作系統(tǒng)安排程序的地址分布。

      程序可以使用一系列相鄰的虛擬地址來(lái)訪(fǎng)問(wèn)物理內(nèi)存中不相鄰的大內(nèi)存緩沖區(qū)。通過(guò)虛擬地址空間與物理地址空間映射解決不連續(xù)的緩沖區(qū)的問(wèn)題。

      2)方便進(jìn)程之間隔離

      不同進(jìn)程使用的虛擬地址彼此隔離。一個(gè)進(jìn)程中的代碼無(wú)法更改正在由另一進(jìn)程使用的物理內(nèi)存。

      3)方便OS使用你那可憐的內(nèi)存。

      程序可以使用一系列虛擬地址來(lái)訪(fǎng)問(wèn)大于可用物理內(nèi)存的內(nèi)存緩沖區(qū)。當(dāng)物理內(nèi)存的供應(yīng)量變小時(shí),

      內(nèi)存管理器會(huì)將物理內(nèi)存頁(yè)(通常大小為 4 KB)保存到磁盤(pán)文件。數(shù)據(jù)或代碼頁(yè)會(huì)根據(jù)需要在物理內(nèi)存與磁盤(pán)之間移動(dòng)。

      虛擬地址空間的布局如下:

      0-3G是用戶(hù)空間? ? ? ? 3-4G是內(nèi)核空間

      用戶(hù)區(qū)? ? ? ? ? ? ? ? ? ? ? ? 內(nèi)核區(qū)

      代碼段

      已經(jīng)初始化的全局變量

      未被初始化的全局變量

      堆 -- 從下往上

      共享庫(kù)

      棧 - 從上往下

      環(huán)境變量

      內(nèi)核區(qū)

      3. C庫(kù)函數(shù)與系統(tǒng)函數(shù)的關(guān)系

      FD:文件描述符 FP_POS:文件指針 BUFFER:緩沖區(qū)

      write對(duì)0-3G的用戶(hù)空間進(jìn)行操作 sys_write()對(duì)3-4G的內(nèi)核空間進(jìn)行操作

      4. IO函數(shù)介紹

      1)open

      查看 man 2 open

      頭文件:

      #include #include #include

      函數(shù)原型:

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

      參數(shù)說(shuō)明

      pathname 文件名

      flags

      必選項(xiàng):

      O_RDONLY 只讀

      O_WRONLY 只寫(xiě)

      O_RDWR 讀寫(xiě)

      可選項(xiàng):

      O_APPEND 追加

      O_CREAT 創(chuàng)建文件

      O_EXCL和O_CREATE一起使用,如果文件存在則報(bào)錯(cuò)

      O_NONBLOCK 非阻塞

      Mode 權(quán)限位,最終(mode&~umask)

      返回值:

      成功:返回最小的可用文件描述符

      失敗:返回-1,并且設(shè)置errno

      open函數(shù)中的errno:

      使用open實(shí)現(xiàn)一個(gè)touch功能

      1 #include 2 #include 3 #include 4 #include 5 #include 6 7 int main(int argc, char *argv[]) 8 { 9 if (argc != 2) 10 { 11 printf("./a.out filename\n") 12 return -1 13 } 14 int fd = open(argv[1], O_CREAT|O_TRUNC|O_WRONLY, 0666); 15 close(fd); 16 17 return 0; 18 }

      一個(gè)進(jìn)程打開(kāi)的最大文件數(shù)(1024)

      1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 8 int main(int argc, char *argv[]) 9 { 10 int num = 3; 11 char filename[128] = {0}; 12 while(1) 13 { 14 sprintf(filename, "temp_%04d", num++); 15 if (open(filename, O_RDONLY|O_CREAT, 0666) < 0) 16 { 17 perror("open err:"); 18 break; 19 } 20 } 21 printf("num == %d\n", num); 22 23 return 0; 24 }

      2)close

      作用:關(guān)閉文件描述符

      頭文件:

      #include

      函數(shù)原型:

      int close(int fd);

      參數(shù)說(shuō)明:

      fd文件描述符

      返回值:

      成功:返回0

      失敗:返回-1,并且設(shè)置errno

      3)read讀

      頭文件

      #include

      函數(shù)原型

      ssize_t read(int fd, void *buf, size_t count);

      參數(shù)說(shuō)明

      fd 文件描述符

      buf緩沖區(qū)

      count緩沖區(qū)大小

      返回值

      失敗:返回-1,設(shè)置errno

      成功:返回讀到的字節(jié)數(shù)

      0代表讀到文件末尾

      非阻塞的情況下read返回-1,但是此時(shí)需要判斷error的值。

      4)write寫(xiě)

      頭文件

      #include

      函數(shù)原型

      ssize_t write(int fd, const void *buf, size_t count);

      參數(shù)說(shuō)明:

      fd文件描述符

      buf緩沖區(qū)

      count緩沖區(qū)大小

      返回值

      失敗:返回-1,設(shè)置errno

      成功:返回寫(xiě)入的字節(jié)數(shù)

      0代表未寫(xiě)入

      實(shí)現(xiàn)一個(gè)cat功能

      1 #include 2 #include 3 #include 4 #include 5 #include 6 7 int main(int argc, char *argv[]) 8 { 9 if (argc != 2) 10 { 11 printf("./a.out filename\n") 12 return -1 13 } 14 int fd = open(argv[1], O_RDONLY); 15 char buf[256] = {0}; 16 int ret = 0; 17 while ((ret = read(fd, buf, ziseof(buf))) != 0) 18 { 19 if (ret == -1) 20 { 21 perror("read err:"); 22 return -1; 23 } 24 else 25 { 26 write(STDOUT_FILENO, buf, ret); 27 } 28 } 29 30 close(fd); 31 32 return 0; 33 }

      需求:給一個(gè)文件中寫(xiě)入內(nèi)容,寫(xiě)完之后打開(kāi)該文件再讀取寫(xiě)入的內(nèi)容?

      bug版本

      1 #include 2 #include 3 #include 4 #include 5 #include 6 7 int main(int argc, char *argv[]) 8 { 9 if (argc != 2) 10 { 11 printf("./a.out filename\n"); 12 return -1; 13 } 14 int fd = open(argv[1], O_RDWR|O_CREAT, 0666); 15 16 char data[12] = "hello world"; 17 write(fd, data, sizeof(data)); 18 19 char buf[256] = {0}; 20 int ret = 0; 21 while ((ret = read(fd, buf, sizeof(buf))) != 0) 22 { 23 if (ret == -1) 24 { 25 perror("read err:"); 26 return -1; 27 } 28 else 29 { 30 write(STDOUT_FILENO, buf, ret); //STDIN_FILENO, STDERR_FILENO 31 } 32 } 33 34 close(fd); 35 36 return 0; 37 }

      結(jié)果:內(nèi)容寫(xiě)入到文件中,但是并未按預(yù)期輸出到屏幕上。

      原因:是由于write完成之后,fd到了文件末尾,因此read時(shí)到了文件末尾,無(wú)法讀取文件數(shù)據(jù)

      解決方法:寫(xiě)完之后將文件指針設(shè)置到文件開(kāi)頭,使用請(qǐng)看下文要介紹的lseek函數(shù)。

      5)lseek寫(xiě)

      頭文件

      #include #include

      函數(shù)原型

      off_t lseek(int fd, off_t offset, int whence);

      參數(shù)說(shuō)明

      fd文件描述符

      offset偏移量

      whence:

      SEEK_SET 文件開(kāi)始位置

      SEEK_CUR 文件當(dāng)前位置

      SEEK_END 文件結(jié)尾

      返回值

      失敗:返回-1,設(shè)置errno

      成功:返回當(dāng)前位置到文件開(kāi)頭的長(zhǎng)度

      lseek作用

      移動(dòng)文件讀寫(xiě)位置

      計(jì)算文件大小

      拓展文件

      示例:

      a.?移動(dòng)文件讀寫(xiě)位置

      修改上例的bug(寫(xiě)入文件內(nèi)容并讀取文件內(nèi)容打印到屏幕)

      1 #include 2 #include 3 #include 4 #include 5 #include 6 7 int main(int argc, char *argv[]) 8 { 9 if (argc != 2) 10 { 11 printf("./a.out filename\n"); 12 return -1; 13 } 14 int fd = open(argv[1], O_RDWR|O_CREAT, 0666); 15 16 char data[12] = "hello world"; 17 write(fd, data, sizeof(data)); 18 //文件讀寫(xiě)位置此時(shí)在末尾 19 //需要移動(dòng)讀寫(xiě)位置 20 lseek(fd, 0, SEEK_SET); //將fd移動(dòng)到文件頭 21 22 char buf[256] = {0}; 23 int ret = 0; 24 while ((ret = read(fd, buf, sizeof(buf))) != 0) 25 { 26 if (ret == -1) 27 { 28 perror("read err:"); 29 return -1; 30 } 31 else 32 { 33 write(STDOUT_FILENO, buf, ret); //STDIN_FILENO, STDERR_FILENO 34 } 35 } 36 37 close(fd); 38 39 return 0; 40 }

      b.?計(jì)算文件大小

      計(jì)算文件大小(輸出文件字節(jié)數(shù))

      1 #include 2 #include 3 #include 4 #include 5 #include 6 7 int main(int argc, char *argv[]) 8 { 9 if (argc != 2) 10 { 11 printf("./a.out filename\n"); 12 return -1; 13 } 14 int fd = open(argv[1], O_RDONLY); 15 16 int ret = lseek(fd, 0, SEEK_END); //將fd移動(dòng)到文件頭 17 printf("file size is %d\n", ret); //注意實(shí)際讀到的文件大小為ret-1 18 19 close(fd); 20 21 return 0; 22 }

      c.?拓展文件

      拓展文件

      1 #include 2 #include 3 #include 4 #include 5 #include 6 7 int main(int argc, char *argv[]) 8 { 9 if (argc != 2) 10 { 11 printf("./a.out filename\n"); 12 return -1; 13 } 14 int fd = open(argv[1], O_WRONLY|O_CREAT, 0666); 15 //拓展文件 16 int ret = lseek(fd, 1024, SEEK_END); //將fd移動(dòng)到文件頭 17 //需要至少寫(xiě)一次,否則不能保存 18 write(fd, "a", 1); 19 printf("file size is %d\n", ret); 20 21 close(fd); 22 23 return 0; 24 }

      阻塞的概念:

      read函數(shù)在讀設(shè)備或者讀管道,或者讀網(wǎng)絡(luò)的時(shí)候。

      輸入輸出設(shè)備對(duì)應(yīng)的/dev/tty。

      6)fcntl

      頭文件

      #include #include

      函數(shù)原型

      int fcntl(int fd, int cmd, ... /* arg */ );

      參數(shù)說(shuō)明:

      fd文件描述符

      cmd 命令

      返回值

      不同的cmd返回值不同

      使用fcntl函數(shù)實(shí)現(xiàn)讀非阻塞

      1 #include 2 #include 3 #include 4 #include 5 #include 6 7 int main(int argc, char *argv[]) 8 { 9 //O_NONBLOCK設(shè)置為非阻塞 10 int fd = open("/dev/tty", O_RDWR); 11 //fcntl()函數(shù),設(shè)置非阻塞 12 int flags = fcntl(fd, F_GETFL); 13 flags |= O_NONBLOCK; 14 fcntl(fd, F_SETFL, flags); 15 16 char buf[256] = {0}; 17 int ret = 0; 18 while(1) 19 { 20 //如果沒(méi)有設(shè)置O_NONBLOCK 21 ret = read(fd, buf, sizeof(buf)); 22 if (ret < 0) 23 { 24 perror("read err:"); 25 printf("ret is %d\n", ret); 26 } 27 28 if (ret) 29 { 30 printf("buf is %s\n", buf); 31 } 32 printf("haha\n"); 33 sleep(1); 34 } 35 close(fd); 36 37 return 0; 38 }

      C 語(yǔ)言 Linux

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶(hù)投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶(hù)投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:Excel如何使用工程函數(shù)在不同數(shù)字系統(tǒng)間進(jìn)行數(shù)值轉(zhuǎn)換?
      下一篇:wps中如何將文字轉(zhuǎn)化成smartart(wps轉(zhuǎn)文字怎么轉(zhuǎn))
      相關(guān)文章
      ZZIJZZIJ亚洲日本少妇JIZJIZ| 亚洲av日韩av高潮潮喷无码| 狼人大香伊蕉国产WWW亚洲| 亚洲美女大bbbbbbbbb| 毛茸茸bbw亚洲人| 亚洲av午夜国产精品无码中文字| 精品亚洲AV无码一区二区| 亚洲伊人tv综合网色| 亚洲乱码一区二区三区在线观看| 亚洲另类激情专区小说图片| 亚洲人成自拍网站在线观看| 亚洲色大成网站www永久网站| avtt天堂网手机版亚洲| 亚洲日本在线播放| 亚洲乱码一二三四五六区| 亚洲欧洲中文日产| 亚洲国产精品午夜电影| 亚洲春色另类小说| 亚洲字幕在线观看| 久久精品国产亚洲AV久| 日本亚洲精品色婷婷在线影院 | 亚洲精品无码久久毛片波多野吉衣| 久久91亚洲精品中文字幕| 亚洲伦理一区二区| 精品亚洲成a人片在线观看少妇| 亚洲精品高清国产一久久| 亚洲一区二区三区高清| 亚洲黄色在线观看视频| 亚洲精品美女在线观看| 亚洲欧洲日产国码www| 亚洲国产熟亚洲女视频| 亚洲精品无码久久久久秋霞| 337P日本欧洲亚洲大胆艺术图| 亚洲?V乱码久久精品蜜桃| 亚洲欧洲中文日韩av乱码| 日韩一卡2卡3卡4卡新区亚洲| 久久精品九九亚洲精品天堂| 亚洲精品人成在线观看| 亚洲fuli在线观看| 亚洲A∨精品一区二区三区下载| 亚洲av日韩片在线观看|