一、文件的打开及创建
函数open打开或创建文件,返回文件描述符。
#include<fcntl.h>
int open(const char *filename, int oflag,.../*[model_t mode]*/);
参数说明:
filename 打开或创建文件的路径名
oflag 整形oflag指定了打开文件的方式, 定义如下
标志 | 含义 |
O_RDONLY | 以只读的方式打开文件 |
O_WRONLY | 以只写的方式打开文件 |
O_RDWR | 以读写的方式打开文件 |
O_APPEND | 以追加的方式打开文件 |
O_CREAT | 创建一个文件 |
O_EXEC | 如果使用了O_CREAT而且文件已经存在,就会发生一个错误 |
O_NOBLOCK | 以非阻塞的方式打开一个文件 |
O_TRUNC | 如果文件已经存在,则删除文件的内容 |
O_RDONLY、O_WRONLY、O_RDWR三个标志只能使用任意的一个。
如果使用了O_CREATE标志,则使用的函数是int open(const char *pathname,int flags,mode_t mode); 这个时候我们还要指定mode标志,用来表示文件的访问权限。mode可以是以下情况的组合:
标志 | 含义 |
S_IRUSR | 用户可以读 |
S_IWUSR | 用户可以写 |
S_IXUSR | 用户可以执行 |
S_IRWXU | 用户可以读、写、执行 |
S_IRGRP | 组可以读 |
S_IWGRP | 组可以写 |
S_IXGRP | 组可以执行 |
S_IRWXG | 组可以读写执行 |
S_IROTH | 其他人可以读 |
S_IWOTH | 其他人可以写 |
S_IXOTH | 其他人可以执行 |
S_IRWXO | 其他人可以读、写、执行 |
S_ISUID | 设置用户执行ID |
S_ISGID | 设置组的执行ID |
除了可以通过上述宏进行“或”逻辑产生标志以外,我们也可以自己用数字来表示,Linux总共用5个数字来表示文件的各种权限:第一位表示设置用户ID;第二位表示设置组ID;第三位表示用户自己的权限位;第四位表示组的权限;最后一位表示其他人的权限。每个数字可以取1(执行权限)、2(写权限)、4(读 权限)、0(无)或者是这些值的和。
二、文件的关闭与删除
函数为close关闭一个打开的文件,函数unlink删除文件
#include<unistd.h>
int close(int filedes);
int unlink(char *pathname);
close关闭文件描述符filedes,成功时返回0,失败返回-1;
unlink删除文件,当且仅当文件的链接数为0时,同时没有被别的进程打开,文件占用的空间才被释放。函数成功时返回0,否则返回-1.
三、文件读写
#include<unistd.h>
size_t read(int fd, void *buf, size_t nbytes);
size_t write(int fd, const void *buf, size_t nbytes);
其中参数buf为指向缓冲区的指针,nbytes为缓冲区的大小(以字节为单位)。函数read()实现从文件描述符fd所指定的文件中读取 nbytes个字节到buf所指向的缓冲区中,返回值为实际读取的字节数。函数write实现将把nbyte个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中,返回值为实际写入的字节数。
四、文件的定位
#include<unistd.h>
int lseek(int fd, offset_t offset, int whence);
lseek将文件读写指针相对whence移动offset个字节。操作成功时,返回文件指针相对于文件头的位置。参数whence可使用下述值:
SEEK_SET | 相对文件开头 |
SEEK_CUR | 相对文件读写指针的当前位置 |
SEEK_END | 相对文件末尾 |
offset可取负值,例如下述调用可将文件指针相对当前位置向前移动5个字节:
lseek(fd, -5, SEEK_CUR);
由于lseek函数的返回值为文件指针相对于文件头的位置,因此下列调用的返回值就是文件的长度:
lseek(fd, 0, SEEK_END);
五、文件的缓冲
#include<unistd.h>
int fsync(int fd);
系统调用fsync将所有已写入文件描述符fd的数据真正的写到磁盘或其它设备中,类似于标准文件库编程中的fflush,当系统调用成功时人才返回0,否则返回-1.
六、复制文件描述符
#include<unistd.h>
int dup(int fd);
int dup2(int fdsrc, int fddes);
dup复制文件描述符fd到当前未使用的最小可用文件描述中。
dup2复制文件描述fdsrc到fddes中。如果fddes已经打开,则关闭之,如果fddes与fdsrc值相等,则直接返回。这两个函数成功时都返回新的文件描述时,否则返回-1。
七、文件控制
1.fcntl
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, int arg);
int fcntl(int fd, int cmd, struct flock *arg);
参数说明:
fd 文件描述词。
cmd 操作命令。
arg 供命令使用的参数。
lock 同上。
fcntl对文件描述符执行各种控制命令,参数cmd确定了具体执行的命令和是否需要参数arg,cmd可选项如下:
F_DUPFD | 复制文件描述词 |
F_SETFD | 设置文件描述词标志 |
F_GETFD | 读取文件状态标志 |
F_SETFL | 设置文件状态标志 |
F_GETFL | 读取文件状态标志 |
F_GETOWN | 获取当前在文件描述词 fd上接收到SIGIO 或 SIGURG事件信号的进程或进程组标识 |
F_SETOWN | 设置将要在文件描述词fd上接收SIGIO 或 SIGURG事件信号的进程或进程组标识 |
F_GETLK | 用于锁处理 |
F_SETLK | 用于锁处理 |
F_SETLKW | 用于锁处理 |
fcbtl专用于锁时,其原形为 int fcntl(int fd, int cmd, struct flock *arg),结构struct flock用于描述锁的信息,定义如下
struct flock{
short l_type; //锁类型,F_RDLCK(申请)读锁,F_WRLCK(申请)写锁,F_UNLCK解锁
short l_whence; //锁区域开始地址的相对位置,取值为SEEK_SET、SEEK_CUR 、SEEK_END之一,与lseek中的whence类似;
long l_start; //锁区域开始地址偏移量。
long l_len; //锁区域的长度,0表示至文件尾。
short l_pid; //拥有所的进程ID号;
}
当fcntl用于锁时cmd的三种取值:
F_GETLCK
F_SETLCK
F_SETLKW
2.文件锁操作
在锁机制的使用中,最常见的有锁的申请、释放的测试等。
a.测试锁
/* 查看文件从start开始len字节内的锁情况 */
void SeeLock(int fd, int start, int len)
{
struct flock arg;
arg.l_type=F_WRLCK;
arg.l_whence = SEEK_SET;
arg.l_start = start;
arg.l_len = len;
if (fcntl(fd, F_GETLK, &arg) == -1) fprintf(stderr, "See Lock failed./n");
else if (arg.l_type == F_UNLCK) fprintf(stderr, "No Lock From %d To %d/n", start, len);
else if (arg.l_type == F_WRLCK) fprintf(stderr, "Write Lock From %d To %d, id=%d/n", start, len, arg.l_pid);
else if (arg.l_type == F_RDLCK) fprintf(stderr, "Read Lock From %d To %d, id=%d/n", start, len, arg.l_pid);
}
b.申请读锁
/* 在文件从start开始len字节内的申请读锁,阻塞模式 */
void GetReadLock(int fd, int start, int len)
{
struct flock arg;
arg.l_type=F_RDLCK;
arg.l_whence = SEEK_SET;
arg.l_start = start;
arg.l_len = len;
if (fcntl(fd, F_SETLKW, &arg) == -1) fprintf(stderr, "[%d] Set Read Lock failed./n", getpid());
else fprintf(stderr, "[%d] Set Read Lock From %d To %d/n", getpid(), start, len);
}
c.申请写锁
/* 在文件从start开始len字节内的申请写锁,阻塞模式 */
void GetWriteLock(int fd, int start, int len)
{
struct flock arg;
arg.l_type=F_WRLCK;
arg.l_whence = SEEK_SET;
arg.l_start = start;
arg.l_len = len;
if (fcntl(fd, F_SETLKW, &arg) == -1) fprintf(stderr, "[%d] Set Write Lock failed./n", getpid());
else fprintf(stderr, "[%d] Set Write Lock From %d To %d/n", getpid(), start, len);
}
d.释放锁
/* 释放文件从start开始len字节内的锁 */
void ReleaseLock(int fd, int start, int len)
{
struct flock arg;
arg.l_type=F_UNLCK;
arg.l_whence = SEEK_SET;
arg.l_start = start;
arg.l_len = len;
if (fcntl(fd, F_SETLKW, &arg) == -1) fprintf(stderr, "[%d] UnLock failed./n", getpid());
else fprintf(stderr, "[%d] UnLock From %d To %d/n", getpid(), start, len);
}