文件描述符
讲到文件 我们就需要知道什么是文件描述符,我们所有对设备和文件的操作都是使用文件描述符来进行的。
通常用fd表示文件描述符。
文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程所打开的文件的记录表
当需要读写文件时,需要把文件描述符作为参数传递给相应的函数。
通常在一个进程启动时,都会打开三个文件:
标准输入:对应的文件描述符为0(STDIN_FILENO)
标准输出:对应的文件描述符为1(STDOUT_FILENO)
标准出错处理:对应的文件描述符为2(STDERR_FILENO)
我们可以通过命令来查看系统文件描述符的个数:
1:cat /proc/sys/fs/file-max
这里面的100624是系统支持的所有用户打开文件描述符的总和
2:ulimit -n
这里的1024是对每个进程的限制,即每一个用户登录后执行的程序占用文件描述符不能超过1024个
文件指针与FILE结构体
每一个进程在PCB(Process Control Block)即进程控制块中都保存着一分文件描述符表,文件描述符就是这个表的索引,文件描述符表中每个表项都有一个指向已打开文件的指针。现在我们明确一下:已打开的文件在内核中用file结构体表示,文件描述符表中的指针指向file结构体。
struct FILE
{
char *_ptr;//文件输入的下一个位置
int _cnt;//当前缓冲区的相对位置
char *_base;//指基础位置(文件的起始位置)
int _flag;//文件标志
int _file;//文件的有效性验证
int _charbuf;//检查缓冲区状况,如果缓冲区则不读取
int _bufsiz;//文件的大小
char *_tmpfname;//临时文件名
};
如上所示
FILE结构体中存放着文件的信息
文件指针与文件描述符的相互转换
#文件描述符转文件指针
FILE *fdopen(int filedes, const char *opentype);
#文件指针转文件描述符
int fileno(FILE *stream);
inode结点
在每一个文件中都会有一项属性,就是inode,它存放着除了文件名以外的所有文件信息,中文名为“索引节点”。
inode包含的文件信息
* 文件的字节数
* 文件拥有者的User ID
* 文件的Group ID
* 文件的读、写、执行权限
* 文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。
* 链接数,即有多少文件名指向这个inode
* 文件数据block的位置
可以用stat命令,查看某个文件的inode信息:
操作系统可以通过这个inode号码来识别不同的文件,并且当遇到文件名无法删除时可以通过inode来删除文件
例如find ./ -inum 812687|xargs rm-f
就可以删掉该文件
可以用df -i来查看每个硬盘分区的inode总数和已经使用的数量:
关于操作文件的函数
open()打开文件
int open(const char *pathname, int flags, mode_t mode);
flags:
//open(文件名,文件访问权限, 文件权限);
//O_CREAT 若文件不存在则创建
//O_RDWR 文件访问的读写权限
//O_APPEND 以追加内容的方式打开文件
//O_EXCL 若创建文件的时候文件存在则报错退出
mode可以不写,默认为664
close()关闭文件
int close(int fd);
lseek()跳转文件指针
off_t lseek(int fd, off_t offset, int whence);
SEEK_SET 从起始位置
SEEK_CUR 从文件指针当前位置
SEEK_END 从文件末尾
offset:偏移的长度
lseek(fd , 1024, SEEK_END);
从文件末尾向前跳转1024字节
read()读文件
ssize_t read(int fd,void* buffer,size_t count);
返回值为读取的实际长度,当读取失败时返回-1
write() 写文件
ssize_t write(int fd, const void *buf, size_t count);
返回实际的写入长度, -1则写入失败
access ()对文件进行判断
int access(const char *pathname, int mode);
F_OK 判断文件是否存在 0-存在
R_OK 判断文件是否可读
W_OK 判断文件是否可写
X_OK 判断文件是否可执行
写一个文件拷贝函数
运行结果如下