博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Linux应用编程--IO

Posted on 2019-07-01 22:38  不上班行不行  阅读(105)  评论(0)    收藏  举报

 文件描述符:

1.文件描述符是一个非负整数,当打开或者创建一个文件的时候,内核向进程返回文件描述符。通过文件描述符可以对文件进行一系列的I/O操作。

2.0,1,2三个文件描述符已经被系统使用,分别代表标准输入,标准输出和错误输出,在系统中的可以用宏来表示分别是STDIN_FILENNO,STDOUT_FILENO,STDERR_FILENO(在头文件unistd.h中)。

3.文件描述符的范围是0~OPEN_MAX-1

4.在没有指定的情况下,让内核返回一个文件描述符的时候(open或者creat),该描述符一定是当前系统中可用的最小的值。

在头文件fcntl.h中

int open(const char* path,int oflag,/*mode_t mode*/): 以指定的符号标志打开或者创建文件。path代表路径,可以是绝对路径也可以是相对路径。mode_t指定文件的权限只有在创建文件的时候使用。

int openat(int fd,const char* path,int oflag,/*mode_t mode*/): 和open基本一样。区别在于该函数可以在指定的fd目录下创建文件,如果path是绝对路径,那么和open完全一样。

常用的文件符号标志:

O_RDONLY:以只读的形式打开文件

O_WRONLY:以写的形式打开文件

O_RDWR:以读写的形式打开文件

O_CREAT:如果文件不存在则创建该文件

O_APPEND:以追加的形式打开文件

O_TRUNC:如果文件存在,并且以写或读写的形式打开,则将其长度截断为0(就是将文件的内容清除而重新打开该文件)

int creat(const char* path,mode_t mode): 和open(path,O_RDWR | O_CREAT | O_TRUNC,mode)所代表的意思完全一致。因为之前系统的open函数并没有O_CREAT这个标志,不能创建文件,所以通常会使用该函数进行文件的创建。

在头文件unistd.h中有如下函数

int close(int fd):关闭文件,成功返回0,失败返回-1

offset lseek(int fd,off_t offset,int whence):移动文件指针,到指定的位置,返回当前的文件位置。fd:文件描述符,offset:偏移量(可以为负数,正数代表从当前位置向后移动,负数代表向前移动),whence:从哪里开始移动,它常用的有三个值

SEEK_CUR:代表当前位置

SEEK_END:代表文件末尾

SEEK_SET:代表文件开头。

在每次打开文件时如果不指定O_APPEND那么偏移量就会被设置为0.

ssize_t read(int fd,void* buf,size_t nbytes):从指定的文件读取数据,返回读取的字节数。若到达文件末尾返回0,出错返回-1。ssize_t代表的是一个有符号数。每次读取都会移动文件指针。并且接着从上次读取到的数据继续读取。

ssize_t write(int fd,void* buf,size_t nbytes):向文件中写入数据,返回写入的字节数,出错返回-1(磁盘已满等)。

提高文件的I/O效率:在linux ext4文件系统中,块的大小为4096,所以在进行读写操作时,如果将缓冲区设置为4096,效率会更好一些。

 预读技术(read ahead):当系统检测到应用程序正在进行顺序读取数据时,系统就会试图读取比应用程序所要求的更多的数据。减少I/O操作次数,提高程序执行的效率

文件共享:类Unix系统支持在不同进程间共享文件

系统中的IO数据结构:打开文件描述符表,文件描述符,文件表项,v节点,i节点

文件描述符表:记录进程所打开的文件

文件描述符:是文件描述符表中的一个记录,包含了文件描述符标志,指向文件表项的指针

文件表项:记录了文件的状态标志,文件的当前偏移量,以及指向v节点的指针

v节点:包含了文件类型和对文件进行操作的函数指针,以及指向i节点的指针。v节点包含的是通用的操作,忽略了文件系统的细节,被称之为虚拟文件系统。在linux系统中没有v节点,取而代之的是通用i节点。

i节点:包含了文件的所有者,文件长度以及文件数据块在磁盘上的位置,和文件系统息息相关。

在linux系统中包含的是通用i节点和与文件系统相关的i节点。

原子操作:由多步组成的一个操作,要么执行完所有的步骤,要么一步也不执行

unistd.h

ssize pread(inf fd,void *buf,size_t nbytes,offf_t offset):先定位到指定的文件位置后读取数据,是原子操作

ssize pwrite(int fd,const void* buf,size_t nbytes,off_t offset):先定位到指定的文件位置后读取数据,是原子操作

int dup(int fd):复制文件描述符,返回一个新的文件描述符,该文件描述符和传入的参数fd的文件指针指向同一个文件表项

int dup2(int fd,int fd2):同样也是复制文件描述符,只不过能够通过指定fd2来要求返回指定的文件描述符,如果该文件描述符已经打开,则先进行关闭操作。

延迟写:在传统的unix系统中,内核通常设有缓冲区高速缓冲或页高速缓冲,在进行I/O操作时,通常先是将数据写入到缓冲区,之后将缓冲区排入到队列中,等到需要写入时才将数据写入。

unistd.h

void sync(void):将修改过的缓存区,排入到写队列中,然后立即返回。

void fsync(int fd):只针对某个文件,将修改过的缓存区,排入到写队列中,并且等待数据写入到磁盘中时返回。

void fdatasync(int fd):和fsync不同是,它的操作对象只是数据,而fsync除了数据外还有文件的属性

int fcntl(int fd,int cmd, ....):可以改变已经打开的文件的属性。

1.复制一个已有的文件描述符(cmd=F_DUPFD和F_DUPFD_CLOEXEC)

2.获取和设置文件描述符标志(cmd=F_GETFD和F_SETFD)

3.获取和设置文件状态标志(cmd=F_GETFL和F_SETFL)

 4.获取和设置异步I/O(cmd=F_GETOWN和F_SETOWN)

5.获取和设置记录锁(cmd=F_GETLk,F_SETLK或F_SETLKW)

需要注意的是在设置文件状态标志时可设置的为:O_APPEND,O_NONBLOCK,O_SYNC,O_DSYNC,O_RSYNC,O_FSYNC,O_ASYNC

sys/ioctl.h

int ioctl(int fd,int request,....):出错返回-1,正确返回其他值。它是一个强大的I/O杂货箱。多用于终端操作。每个设备驱动程序都可以定义他自己的一组ioctl命令,而系统则为不同的ioctl命令提供通用的ioctl命令。

在较新的系统中会有/dev/fd/这个目录,目录项为名字为0,1,2等的文件名。打开这些文件等效与复制了文件描述符。

如: int fd = open("/dev/fd/0",mode)  等效与int fd = dup(0),因为共用一个文件表项,所以初次打开时能进行什么操作,复制后才能进行什么操作。