系统调用接口
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: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。 可选参数:
O_RDONLY: 只读打开 O_WRONLY: 只写打开 O_RDWR : 读,写打开
上面这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
O_TRUNC:打开同时截断文件为0长度 - mode:文件创建权限(最后文件的权限是mode &~ umask)
可以通过mode_t umask(mode_t mask);函数将当前进程的文件创建权限掩码修改为mask
- 返回值:
成功:新打开的文件描述符
失败:-1
write
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
- 参数:
fd: open打开文件所返回的文件描述符
buf:要写入的数据
count:要写入的字节数 - 返回值:实际写入的字节数 失败:-1
read
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
从fd文件中读取count长度的数据放到buf中
返回值:返回实际读取到的字节数, 失败: -1
lseek
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
跳转到fd文件的读写位置到指定处
whence : SEEK_SET(文件头) SEEK_CUR(当前) SEEK_END(文件尾)
offset: 偏移量(负值表示whence向前位置)
close
#include <unistd.h>
int close(int fd);
关闭一个文件描述符 , 使它不再指向任何文件和可以在新的文件操作中被再次使用.任何与此文件相关联的以及程序所拥有的锁, 都会被删除(忽略那些持有锁的文件描述符)
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
int main() {
//将当前进程的文件创建权限掩码修改成为mask
umask(0);
int fd = open("./test.txt", O_RDWR | O_CREAT | O_APPEND | O_TRUNC, 0777);
if (fd < 0) {
perror("open error");
return -1;
}
char* buf = "hello ya\n";
ssize_t ret = write(fd, buf, strlen(buf));
if (ret < 0) {
perror("write error");
return -1;
}
lseek(fd, 0, SEEK_SET);
char buff[1024] = { 0 };
ret = read(fd, buff, 1023);
if (ret < 0) {
perror("read error");
return -1;
}
printf("ret:%d-[%s]]\n", ret, buff);
close(fd);
return 0;
}
文件描述符fd
文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件。
- Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2。
文件描述符的分配规则:最小未使用
体会最小未使用:下述代码首先关闭了默认打开的标准输出文件,然后打开“./test.txt”文件,这时printf的内容并没有打印到显示器,而是写到了“test.txt”文件中。
int main() {
close(1);
int fd = open("./test.txt", O_CREAT | O_RDWR, 0664);
if (fd < 0) {
perror("open error");
return -1;
}
printf("fd:%d\n", fd);
close(fd);
return 0;
}
注:printf函数使用的是write接口,操作的是fd为1的文件。因为1被关闭,这时最小未使用的文件描述符为1,所以打开“test.txt”文件时被分配为1。printf打印的内容就被打印到文件描述符为1的文件即“test.txt”文件。
重定向
重定向指的是文件描述符的重定向;文件描述符这个下标中的文件描述信息,从-一个文件变成了另- -个文件;
这时候当用户通过文件描述符向文件写入数据的时候,文件描述符并没有变,依然还是相同的数字;但是因为描述符下标中的文件描述信息的改变,而导致数据流向另-个文件(像上面的printf)
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
将oldfd描述符对应的描述信息,向newfd中拷贝一份
让newfd也指向oldfd所指向的文件
若newfd本身已经有打开的文件,则关闭关闭这个文件