输入/输出
:在主存和外部设备(如磁盘驱动器,终端和网络)之间拷贝数据的过程。
输入
:从I/O设备拷贝数据到主存
输出
:从主存拷贝数据到I/O设备
所有的I/O设备,如网络、磁盘和终端,都被模型化为文件。对其输入和输出被当作相应文件的读和写。
打开文件
:一个应用程序要访问一个I/O设备,即要求内核打开相应文件。
描述符
:内核返回一个小的非负整数,在后续对此文件的所有操作中标识这个文件。
标准输入(描述符0):STDIN_FILENO
标准输出(描述符1):STDOUT_FILENO
标准错误(描述符2):STDERR_FILENO
文件位置
:从文件开头起始的字节偏移量k。应用程序能够通过执行seek操作,显式设置文件当前位置
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(char *filename,int flags,mode_t mode);
返回值:若成功,则返回在进程中当前没有打开的最小描述符,若出错,则为-1
flags:
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:可读可写
mode:mode与umask共同指定了新文件的访问权限位。
文件的访问权限位:mode & ~umask
umask:umask需要在打开文件前使用函数umask(umask);
进行设置
#include <unistd.h>
int close(int fd);
#include <unistd.h>
ssize_t read(int fd,void *buf, size_t n);
返回:若成功则为实际传送的字节数量;-1表示错误;0表示EOF
fd:源文件的描述符
n:拷贝最多n个字节
buf:目标存储器位置
ssize_t write(int fd,const void *buf, size_t n);
返回:若成功则为实际写的字节数量;-1表示错误
buf:源存储器位置
n:拷贝最多n个字节
fd:目标文件的描述符
size_t 被定义为unsigned int
ssize_t 被定义为int
不足值出现情况:
读时遇到EOF
从终端读文本行
读和写网络套接字
无缓冲输入输出:
#include “csapp.h”
ssize_t rio_readn(int fd, void usrbuf, size_t n);
ssize_t rio_writen(int fd, void usrbuf, size_t n);
返回:
成功:传送的字节数
EOF:0
出错:-1
带缓冲的输入函数:
文本行
:一个由换行符(0x0a)结尾的ASCII码字符序列
每打开一个描述符都会调用一次rio_readinitb函数,将描述符fd和地址rp处的一个类型为rio_t的读缓冲区联系起来
void rio_readinitb(rio_t *rp, int fd);
rio_readlineb函数从文件rp读一个文本行(包括换行符),到存储器位置usrbuf,用空字符结束文本行。至多读maxlen-1个字节,余下一个字符留给结尾空字符。超过maxlen-1部分会被截断。
ssize_t rio_readlineb(rio_t rp,void usrbuf, size_t maxlen);
rio_readnb从文件rp最多读n个字节到存储器位置usrbuf。
ssize_t rio_readnb(rio_t rp,void usrbuf, size_t n);
返回:
成功:读的字节数
EOF:0
出错:-1
对同一描述符,带缓冲区的函数调用可以任意交叉进行,但他们和无缓冲的调用不应交叉使用。
#include <unistd.h>
#include <sys/stat.h>
int stat(const *filename, struct stat *buf);
int fstat(int fd, struct *buf);
返回:成功为0;出错为-1
stat以文件名为输入,fstat以文件描述符为输入。
描述符表:由进程打开的文件描述符来索引,每个打开的表项指向文件表中的一个表项
文件表:当前文件位置,引用计数(当前指向该表项的描述符项数),以及一个指向V-node表对应表项的指针
v-node表:包括st_mode和st_size成员
#include <unistd.h>
int dup2(int oldfd, int newfd);
成功为非负描述符,出错为-1.
拷贝表项oldfd到表项newfd,覆盖newfd以前的内容。
《深入理解计算机系统》(第二版)