目录
1、文件有哪些操作?
1、打开文件,函数open()
2、读取文件,函数read()
3、写文件,函数write()
4、关闭文件,函数close()
5、控制文件,函数ioctl()
2、文件表和文件描述符
当系统打开一个文件时,会把文件的各种信息放入一段内存中,这段内存叫文件表,但文件表比较大,不利于传参等参数,因此文件表不对外提供,对外提供文件表的编号,这个文件表的编号叫文件描述符。文件描述符的本质就是一个非负整数,必须对应一张文件表才有效。每个进程都有自己的文件描述符的总表,记录了文件描述符和文件表的对应关系。
“0” “1” “2”已经被系统预先使用,代表标准输入、标准输出和标准错误。表述符从3开始,最大到OPEN_MAX(Linux一般是256个)。
文件描述可以循环利用。close()以后可以再次使用。
3 函数详解
3.1 open()函数
头文件:
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int open(const char*filename,int flags,...)
参数filename 就是文件名(包括路径),参数flags是打开的标志,主要包括:
O_RDONLY (只读),O_WRONLY(只写) ,O_RDWR(读写):打开的权限,三个必选其一。
O_CREAT : 创建标识,文件存在就打开,不存在就新建。
O_TRUNC : 打开文件时,自动清空文件(open()时清空)。
O_EXCL : 文件不存在,新建,文件存在就返回-1代表出错。
这两个一般结合O_CREAT使用。
O_APPEND : 采用追加的方式打开文件,一般用于写
参数 “...”代表0-n个任意类型的参数,open()函数的第三个参数只在新建文件时有用,传入文件在硬盘上的权限。成功返回文件描述符,失败返回-1.
注:文件在硬盘上的权限与程序无关,程序的权限是打开权限,打开权限应该是文件在硬盘上的权限的一部分。
返回,成功返回文件描述符,失败返回-1.
3.2 read()
头文件
ssize_t read(int fd,void* buf,size_t count);
功能:从指定文件读取数据
描述:
fd是文件描述符,buf是传出参数,count是你想要读的大小,一般就是buf指向的内容的大小,当然,也可以比其小。
返回,成功返回读到的字节数,失败返回-1
3.3 write()
头文件
#include<unistd.h>
ssize_t write(int fd,const void* buf,size_t length)
功能:向指定文件写入数据
描述:
fd是文件描述符,buf是要写入的数据的指针,length是要写入数据的大小。
返回,写入成功返回写入数据的大小,失败返回-1
3.4 close
头文件
#include<unistd.h>
int close(int fd);
功能:关闭一个文件描述符
描述:
fd 是要关闭的文件描述符
返回,如果成功返回0,失败返回-1.
3.5 lseek()
头文件:
#include<sys/types.h>
#include<unistd.h>
off_t lseek(int fd,off_t offset,int whence);
功能:指定文件读写的位置
描述:
fd文件描述符,offset 是偏移量,whence是偏移的起始位置,有三个值:
SEEK_SET --从文件头开始计算偏移
SEEK_CUR --从当前位置计算偏移
SEEK_END --从文件尾计算偏移
返回:移动以后的位置和文件头的距离,返回失败-1。
注:这个返回值可以用来获取文件的大小,标C中要用fseek()+ftell()获取文件的大小。使用vi时,大多数情况下wq会自动加一个vi的结束符,因此会多一个字节。一般都使用SEEK_SET,个别时候使用SEEK_END
3.6 fcntl()
头文件:
#include<unistd.h>
#include<fcntl.h>
int fcntl(int fd,int cmd,...);
功能:对文件加锁
描述:
参数fd就是文件描述符,cmd是命令,...代表0-n个任意类型的参数
返回和cmd的选择有关。
cmd主要包括:
F_DUPFD - 复制文件描述符,需要传入第三个参数做新的描述符的值,如果这个值已经被使用,找大于该值的未使用的最小值。
F_SETFL/F_GETFL -设置/获取文件描述符的状态,SETFL基本用不到,因为只能修改O_APPEND;F_GETFL不需要第三个参数,可以获取权限和O_APPEND,创建标识无法获取。
F_SETLK/F_SETLKW -设置文件锁
文件锁 允许多个文件同时读,但不允许同时写,有的读有的写也不行。因此文件锁分为读锁和写锁。读锁针对读操作,效果允许其他进程读文件,但是不允许写。写锁针对写操作,效果是不允许其他进程读和写。
文件锁的使用是一个函数+一个结构:
fcntl()函数 + struct flock(失败返回-1)
fcntl(int fd,F_SETLK/F_SETLKW,struct flock*)。
struct flock{
short l_type;//锁的类型,包括读锁、写锁和释放锁
short l_whence;//锁定起始点的参考位置
off_t l_start; //锁定起始点的偏移量
off_t l_len; //锁定区域的大小,锁定的长度
pid_t l_pid; //锁定进程的pid,只有GETLK时用到,给-1即可
};
l_type锁的类型:F_RDLCK(读锁)/F_WRLCK(写锁)/F_UNLCK(解锁)
l_whence的值:SEEK_SET(从文件开始)/SEEK_END(从文件结束)/SEEK_CUR(从文件的当前位置)
注:文件锁不是锁定整个文件,而是锁文件的一部分。锁定的部分由l_whence
/l_start和l_len三个联合决定。
比如:l_whence选SEEK_SET,l_start=10,l_len=20。锁定区域是:第11个到
第30个
文件锁其实并不能锁定读写函数,读写的函数read()/write(),只能阻止其他进程的加锁行为,导致其他进程加不上锁。因此文件锁的正确用法是:在调用read()之前应该加一个读锁,在调用write()之前加一个写锁,读写完毕以后记得马上释放锁。
锁定的方式有两种,一种是F_SETLK,锁定失败立即返回-1,另一种是F_SETLKW,锁不上就一直等待,等到别人释放锁以后继续上锁。
F_GETLK 不是获得锁,是测试一个锁能不能加上,不会真的加锁。
3.7 access()函数
头文件
#include<unistd.h>
#include<fcntl.h>
int access(const char *pathname,int mode)
功能:判断文件的状态
描述:
pathname是文件名(包括路径),mode,模式包括四个宏:
R_OK 是否有读权限
W_OK 是否有写权限
X_OK 是否有执行权限
F_OK 文件是否存在
如果有或存在,返回0,取的是当前用户的权限
4、目录的操作
在Unix中,可以在程序里操作目录,包括:
1、新建目录,mkdir()
2、删除目录,rmdir()
3、切换当前目录,相当于cd命令,chdir()。
4、打开一个目录,opendir()
5、读取目录的内容(子项,子文件或子目录),readdir()
6、关闭已经打开的目录(不关闭也可以),closedir()
一般读取某个目录内容(子项)的步骤:
1、opendir()返回目录指针。
2、循环调用readdir(),注意读取每个子项。
3、closedir()关闭目录,这步可以省略。
5、目录操作的函数
5.1 mkdir()
头文件:
#include<sys/stat.h>
#include<sys/types.h>
int mkdir(const char* pathname,mode_t mode);
功能:创建一个新目录。
描述:pathname是要创建的目录路径,mode是该目录的权限,如果没有安全的要求,建议给”0777”。
返回,如果成功返回0,失败则返回-1.
5.2 rmdir()
头文件:
#include<unistd.h>
int rmdir(const char* pathname)
功能:删除一个目录
描述:
pathname是一个目录的路径
返回,如果成功,返回0,失败则返回-1.
5.3 chdir()
头文件:
#include<unistd.h>
int chdir(const char* path)
功能:切换当前工作目录
描述:
path是要改为的目录的路径
返回,如果成功,返回0,失败则返回-1.
5.4 opendir()
头文件:
#include<sys/types.h>
#include<dirent.h>
DIR* opendir(const * name)
功能:打开一个目录
描述:
name是目录的路径
返回,成功则返回该目录的指针,失败返回NULL,即0.
5.5 readdir()
头文件:
#include<dirent.h>
struct dirent* readdir(DIR* dirp)
功能:读取一个目录里面的子项。
描述:
dirp是目录的文件指针
如果成功,返回一个结构体指针,
struct dirent{
Ino_t d_ino;
Off_t d_off;
Unsigned short d_reclen;
Unsigned char d_type;
Char d_name[256];
}
如果失败,返回NULL。
5.6 closedir()
头文件:
#include<sys/types.h>
#include<dirent.h>
int closedir(DIR* dirp)
功能:关闭一个目录指针。
描述:
dirp是要关闭的目录指针。
返回,如果成功,返回0,失败返回-1.