一 使用文件描述符
1 打开关闭文件描述符
open creat 使用他们需包含头文件<sys/types.h> <sys/stat.h>和<fcntl.h>
int open(const char *pathname,int flags)
int creat(const char *pathname,int flags,mode_t mode)
pathname:路径名
flag:访问该文件的方式,O_RDONLY O_WRONLY O_RDWR
mode:包含了文件在创建时的模式
O_CREAT 如果文件不存在则建立文件
O_EXCL 仅与O_CREAT连用,如果文件已经存在,则强制open失败
O_NOCTTY 如果打开的文件是一个终端,就不会成为打开其进程的控制终端
O_TRUNC 如果文件存在,则将文件的长度截为0
O_APPEND 将文件指针设置到文件的结束处
O_NONBLOCK 如果读操作没有blocking则无法完成时,读操作返回0字节
O_NODELAY 同O_NONABLOCK
O_SYNC 在数据被物理地写入磁盘或其他设备之后操作才返回
fd=open(path,O_CREAT|O_TRUNC|O_WRONLY,0644);
2 读写文件描述符
#inlcue<unistd.h>
ssize_t read(int fd,const void *buf,size_t count);
ssize_t write(int fd,const void *buf,size_t count);
3 使用ftruncate缩短文件
#include<unistd.h>
int ftruncate(int fd,off_t length)
4 使用lseek定位文件指针
函数lseek在用描述符fd打开的文件里吧文件指针设定到相对于whence值偏移offset的位置,文件指针是文件中执行读写操作的位置
#include<sys/types.h>
#include<unistd.h>
off_t lseek(int fd,off_t offset,int whence)
whence:
SEEK_SET 设置文件指针到文件内offset字节
SEEK_CUR 设置指针的位置相对于当前位置向前offset字节处,offset可以为负
SEEK_END 设置指针的位置为从文件结尾往回offset字节处
使用fsync同步到硬盘
#include <unistd.h>
int fsync(int fd);
5 使用fstat获得文件信息
系统调用fstat返回文件描述符fd引用的文件的相关信息,并把结果保存在buf指向的结构struct stat中
#include<sys/stat.h>
int fstat(int fd,struct stat *buf);
struct stat
{
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
dev_t st_rdev;
off_t st_size
unsigned long st_blksize
unsigned long st_blocks
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
}
S_ISLNK(mode) 符号链接
S_ISREG(mode) 普通文件
S_ISDIR(mode) 目录
S_ISCHR(mode) 字符设备
S_SIBLK(mode) 块设备
S_ISFIFO(mode) FIFO
S_ISSOCK(mode) 套接字
利用S_IFMT掩盖文件模式中的文件类型比特位,只显示权限位和修饰位的文件模式
6 mkstemp linux中临时文件创建函数
mkstemp只有一个参数,这个参数是以“XXXXXXXXX”结尾的
7 使用fchown改变文件所有权
系统调用fchown是程序员使用的chown命令的等价体,它能让你改变与打开文件相关联的所有者和所有组。
#include <sys/types.h>
#include<unistd.h>
int fchown(int fd,uid_t owner,gid_t group);
8 使用fchmod改变文件读写权
fchmod调用把fd引用的文件的权限位改为mode指定的八进制模式。
int fchmod(int fd,mode_t mode)
9 flock
int flock(int fd,int operation)
operation:
LOCK_SH 共享性锁
LOCK_EX 排斥性锁
LOCK_NB 可以和其他值进行“或”操作以防上锁
在任何特定时刻,在一个文件上只能有一个进程施加排斥性锁,但是可以有多个进程施加共享性锁。只有当一个程序试图施加它自己的锁时,锁才会起作用;而没有尝试对文件上锁的程序仍然能够访问该文件。因此,锁只能在协同工作的程序间起作用。
访问一个上锁文件的步骤
1)检查是否有锁
2)如果文件没有锁,则建立自己的锁
3)打开文件
4)对文件作必要的处理
5)关闭文件
6)对文件解锁
文件锁有两种类型:建议性锁和强制性锁
建议性锁(advisory lock)也称为合作性锁,它依赖这样的约定,每个使用上锁文件的进程都要检查是否有锁存在,并且尊重已有的锁
强制性锁(mamdatory lock)是由内核所执行的,当一个文件被上锁以进行写入操作的时候,在锁定该文件的进程释放该锁之前,内核会阻止任何对该文件的读或写访问
有两种实现上锁的方法:
锁定文件和记录锁定
flock用于向文件施加建议性锁
fcntl和它的包裹函数lockf既能向文件施加建议性锁也能施加强制性锁,系统调用fcntl符合posix标准。
记录锁:对于文件一部分而不是整个文件的锁,这种对上锁行为更为细致的控制似的进程能够更好的写作以共享文件资源
读取锁也叫共享锁,因为多个进程能够在文件的同一部分上建立读取锁
写入锁经常被成为排他锁,因为任何时刻只能有一个进程在文件的某个部分上建立写入锁。
#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);
fcntl改变和文件描述符fd相关联的属性,参数cmd控制fcntl作什么。
cmd:
F_DUPFD 复制文件描述符fd
F_GETFD 获得fd的close-on-exec标志,如果标志没有设置,仍为0,则文件经过exec系列调用之后仍然保持打开状态
F_SETFD 设置close-on-exec标志以便在arg中传送的值
F_GETFL 得到open设置的标志
F_SETFL 改变open设置的标志
F_GETLK 得到离散的文件锁
F_SETLK 设置获得离散的文件锁,不等待
F_SETLKW 设置获得离散的文件锁,在需要时,等待
F_GETOWN 检查将收到SIGIO和SIGURG信号的进程ID或进程组号
F_SETOWN 设置进程ID或进程组号
在设置锁,需传值为F_SETLK或F_SETLKW的参数,设置lock.l_type的值为F_RDLCK(用于读取锁)F_WRLCK(用于写入锁)。要清除锁,则设置lock.l_type的值为F_UNLCK,无论设置或者清空,如果操作成功,fcntl都返回0。如果不能设置锁则返回-1
要检查锁的状态,可以使用F_GETLK,,如果另一个进程已经设置了所,则会在flock*的机构中填满相关的信息。
10 使用dup和dup2调用
系统调用dup和dup2能够复制文件描述符。dup返回新的文件描述符(没使用的文件描述符最小的编号)。dup2可以让用户指定返回的文件描述符的值,如果需要,则首先接近newfd的值,它通常用来重新打开或重定向一个文件描述符。
#include<unistd.h>
int dup(int oldfd);
int dup2(int oldfd,int newfd);
新老描述符共享文件的偏移量、标志和锁,但不共享 close-on-exec标志
dup2(fd,STDOUT_FILENO)
close(fd);
close(STDOUT_FILENO);
11 使用select同时读写多个文件
int select(int n,fd_set *readfds,fd_set *writefds,fd_set exceptfds,struct timeval *timeout)
在readfds中的文件描述符集合,用于可读取文件
在writefds中的集合查看他们能否写入数据
在exceptfds中的几何,用于异常
当I/O操作没有等待就立即返回时,称之为非阻塞式I/O调用。
第一个参数n包含了在任何受监视集合中最高编号的文件描述符再加1,如果出现错误,select返回-1
在出现错误的情况下,select也使所有的文件描述符几何和timeout为空,所以在重新使用它们之前,你必须吧他们重新设置为有效值。