
达者为先 师者之意
Linux 系统编程之文件编程
1 文件描述符(fd)
Linux文件的身份证号码
文件描述符是一个非负的整数,当打开一个文件或创建一个文件时,内核向进程返回一个标识该文件的整数,即fd。
注意,若文件不被创建打开(即没有载入进程),是没有文件描述符可言的。
必需明确一个概念;UNUX中的一切皆是文件。因此对于特殊的文件有特殊的文件描述符。
linux中, 每一个进程在内核中,都对应有一个“打开文件”数组,存放指向文件对象的指针,而 fd 是这个数组的下标。
我们对文件进行操作时,系统调用,将fd传入内核,内核通过fd找到文件,对文件进行操作。既然是数组下标,fd的类型为int,< 0 为非法值,>=0 为合法值。在Linux中,一个进程默认可以打开的文件数为1024个,fd的范围为0~1023。可以通过设置,改变最大值。
在linux中,值为0、1、2的fd,分别代表标准输入、标准输出、标准错误输出。
2 文件的创建(creat)
头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型
int creat(const char *filename,mode_t mode);
filename:要创建的文件名(包含路径、缺省为当前路径)
mode:创建模式 //可读可写可执行
常见创建模式:
宏表示 数字
S_IXUSR 1 可执行
S_IWUSR 2 可写
S_IRUSR 4 可读
S_IRWXU 7 可读、写、执行
creat函数的返回值
成功:返回文件描述符
出错:返回-1并设置errno
3 文件打开(open)
头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
两种函数原型
int open(const char *pathname, int flags); //不需要创建新文件
int open(const char *pathname,int flags,mode_t mode); //创建新文件
pathname是要打开或创建的文件的名字(包含路径名称,缺省是认为在当前路径下面)
flags可以去下面的一个值或者是几个值的组合:
- 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_IRWXG 组可以读写执行
- S_IROTH 其他人可以读
- S_IWOTH 其他人可以写
- S_IXOTH 其他人可以执行
- S_IRWXO 其他人可以读、写、执行
- S_ISUID 设置用户执行ID
- S_ISGID 设置组的执行ID
除了可以通过上述宏进行“或”逻辑产生标志以外,
我们也可以自己用数字来表示,
Linux总共用5个数字来表示文件的各种权限:
第一位表示设置用户ID;第二位表示设置组ID;第三位表示用户自己的权限位:第四位表示组的权限;最后一位表示其他人的权限。
每个数字可以取1(执行权限)、2(写权限)、4(读权限)、0(无)或者是这些值的和。
0100:可执行
0200:可写
0400:可读
0600:可读,可写:
0700:可读,可写,可执行
如果打开成功返回文件描述符fd
如果打开失败出错返回-1并设置errno
4 文件关闭(close)
头文件
#include <unistd.h>
函数原型
int close(int fd);
将要关闭的文件描述符传入close函数中即可关闭该文件
5 文件的写入(write)
头文件
#include <unistd.h>
函数原型
ssize_t write(int fd, const void *buf, size_t count);
fd: 文件描述符;
buf: 指定的缓冲区,即指针,指向一段内存单元;
count:要写入文件指定的字节数;
该函数就是把缓存区的数据写入到文件中去;
write函数的返回值
成功:写入文档的字节数
失败:-1
成功时返回写的字节数,错误时返回-1
6 文件的读取(read)
头文件
#include <unistd.h>
函数原型
ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符;
buf:指定的缓冲区,即指针,指向一段内存单元;
count:你要读取文件的字节数;
read函数的返回值
成功:返回读取的字节数
出错:返回-1并设置errno
如果在调read之前已到达文件末尾,就是啥都没读到,则这次read返回0。
7 文件光标的移动、计算文件大小(lseek)
头文件
#include <sys/types.h>
#include <unistd.h>
函数原型
off_t lseek(int fd, off_t offset, int whence);
fd:文件描述符;
offset:向后的偏移值,对whence的偏移值,整数往后,负数往前;
whence:
- SEEK_SET 参数 offset即为新的读写位置(文件头)
- SEEK_CUR 以目前的读写位置往后增加 offset 个位移量(当前光标位置)
- SEEK_END 将读写位置指向文件尾后再增加 offset个位移量(文件尾)
当 whence 值为 SEEK_CUR 或 SEEK_END 时, 参数 offet 允许负值的出现
下列是特别的使用方式:
- 欲将读写位置移到文件开头时:
lseek(fd,0, SEEK_SET);- 欲将读写位置移到文件尾时:
lseek(fd,0, SEEK_END);- 想要取得目前文件位置时:
lseek(fd,0, SEEK_CUR);lseek函数的返回值
- 成功:返回目前的读写位置, 也就是距离文件开头多少个字节.
- 失败:则返回-1, errno 会存放错误代码.
lseek函数计算文件的大小
通过 lseek 的返回值来计算内容大小。
lseek(fd,0,SEEK_END);
码字不易 求个三连
