文件IO内核表示
1、内核中的三种数据结构
1.1文件描述符表
文件描述符标志
文件表项指针
1.2 文件表项
文件状态标志
读、写、追加、同步和非阻塞等状态标志
当前文件偏移量
i节点表项指针
引用计数器
1.3 节点
文件类型和对该文件的操作函数指针
当前文件长度
文件所有者
文件所在的设备、文件访问权限
指向文件数据在磁盘块上的所在位置的指针等。
2、dup和dup2函数
#include<unistd.h>
int dup(int oldfd);
int dup2(int oldfd,int newfd);
返回:成功返回新文件描述符,出错返回-1
功能:文件描述符的复制
- 参数
- oldfd:原先的文件描述符
- newfd:新的文件描述符
- 由dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。
- 用dup2则可以用newfd参数指定新描述符的数值。如果newfd已经打开,则先将其关闭。如若oldfd等于newfd,则dup2返回newfd,而不关闭它。
- 在进程间通信时可用来改变进程的标准输入和标准输出设备。
- 示例:
int main(int argc,char* argv[])
{
int i=1;
for(;i<argc;i++)
{
if(!strcmp(argc[i],"+"))
{
if(fd=open(argv[++i],O_RDOULY)<0)
{
sys_err("open");
}
else
{
if(dup2(fd,STDIN_FILENO)!=STDIN_FILENO)
{
sys_err("dup2");
}
close(fd);
}
}
else if(!strcmp(argv[i],"-"))
{
int fd=open(argv[++i],O_WRONLY|O_TRUNC,077);
if(fd<0)
{
sys_err("open");
}
else
{
if(dup2(fd,STDIN_FILENO)!=STDIN_FILENO)
{
sys_err("dup2");
}
close(fd);
}
}
else
{
fprintf(stderr,"usere:%s[+]file2[-]file2\n",argv[0]);
exit(1);
}
copy(STDIN_FILENO,STDIN_FILENO);
return 0;
}
}
3、fcntl函数
#include<unistd.h>
#include<fcntl.h>
int fcntl(int fd,int cmd);
int fcntl(int fd,int cmd,long arg);
int fcntl(int fd,int cmd,struct flock * lock);
返回:成功则依赖于cmd,出错返回-1
功能:可以改变已经打开文件的性质
3.1常见的功能
-
复制一个现存的描述符,新文件描述符作为函数值返(
cmd=F_DUPFD
) -
获得/设置文件描述符标志(
cmd=F_GETFD或F_SETFD
) -
获得/设置文件状态标志(
cmd=F_GETFL 或F_SETFL
) -
获得/设置文件锁(
cmd=F_SETLK、F_SETFD、F_SETLKW)
- 第三个参数为struct flock结构体
3.2 cmd的常见取值
F_DUPFD: 复制文件描述符,新的文件新的文件描述符作为函数返回值返回。
F_GETFD/F_SETFD : 获取/设置文件描述符,通过第三个参数设置
F_GETFL/F_SETFL :
①获取/设置文件状态标志,通过第三个参数设置
②可以更改的几个标志是:O_APPEND,O_NONBLOCK,SYNC,O_ASYNC (O_RDONYL、O_WRONLY和O_RDWR
不适用)
示例:
// 1 增加文件状态
//获取原来的文件状态标志
int val=fcntl(fd,F_GETFL);
//增加新的文件状态标志
val|=flag;
//重新设置文件状态标志
fcntl(fd,f_SETFL,val);
// 2 修改文件状态
//获取原来的文件状态标志
int val=fcntl(fd,f_GETFL);
//清除指定的文件状态标志
val&=~flag;
//重新设置文件状态标志
fcntl(fd,f_SETFL,val);
4、I/O处理的五种模型
1)、阻塞I/O模型
若所调用的I/O函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回。如:终端、网络设备的访问。
2)、非阻塞模型
当请求的I/O操作不能完成时,则不让进程休眠,而且返回一个错误。如:open read write请问。
3)、I/O多路转接模型
如果请求的I/O操作阻塞,且他不是真正阻塞I/O,而且让其中的一个函数等待,在这期间,I/O还能进行其他操作。如:select函数
4)、信号驱动I/O模型
在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。
5)、异步I/O模型
在这种模型下,当一个描述符已准备好,可以启动I/O时,进程会通知内核。由内核进行后续处理,这种用法现存较少。
非阻塞I/O
- 低速系统调用时,进程可能会阻塞
- 非阻塞I/O确定操作(read open write)不阻塞,如果操作不能完成,则出错返回。
- 设定非阻塞的方式
- 使用open打开文件,设置o_NONBOCK标志。
- 如果一个文件已经打开,则使用fcntl修改文件状态标志。
//设置非阻塞IO
set_fl(STDIN_FILENO,O_NONBLOCK);