【Linux C編程】第七章 系統(tǒng)IO函數(shù)2
一、整體大綱
二、 系統(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)題?
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
函數(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
一個(gè)進(jìn)程打開(kāi)的最大文件數(shù)(1024)
1 #include
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
需求:給一個(gè)文件中寫(xiě)入內(nèi)容,寫(xiě)完之后打開(kāi)該文件再讀取寫(xiě)入的內(nèi)容?
bug版本
1 #include
結(jié)果:內(nèi)容寫(xiě)入到文件中,但是并未按預(yù)期輸出到屏幕上。
原因:是由于write完成之后,fd到了文件末尾,因此read時(shí)到了文件末尾,無(wú)法讀取文件數(shù)據(jù)
解決方法:寫(xiě)完之后將文件指針設(shè)置到文件開(kāi)頭,使用請(qǐng)看下文要介紹的lseek函數(shù)。
5)lseek寫(xiě)
頭文件
#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
b.?計(jì)算文件大小
計(jì)算文件大小(輸出文件字節(jié)數(shù))
1 #include
c.?拓展文件
拓展文件
1 #include
阻塞的概念:
read函數(shù)在讀設(shè)備或者讀管道,或者讀網(wǎng)絡(luò)的時(shí)候。
輸入輸出設(shè)備對(duì)應(yīng)的/dev/tty。
6)fcntl
頭文件
#include
函數(shù)原型
int fcntl(int fd, int cmd, ... /* arg */ );
參數(shù)說(shuō)明:
fd文件描述符
cmd 命令
返回值
不同的cmd返回值不同
使用fcntl函數(shù)實(shí)現(xiàn)讀非阻塞
1 #include
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)容。