目录
开关读写
头文件
打开
关闭
读写
文件描述符
重定向
命令行重定向:
使用dup函数在文件内进行重定向
#include
#include
#include
#include
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
pathname:文件路径,需包含想打开的文件名
flags:打开方式,底层是位图
O_WRONLY -- 只写,从头开始写,但默认不会对原始文件内容做清空
O_RDONLY -- 只读
O_CREAT -- 如果没有这个文件则创建
O_TRUNC -- 清空文件
O_APPEND -- 追加,不是写入,需要有O_WRONLY一起才能写
O_RDWR -- 读写
mode:新建文件的权限
打开成功返回文件描述符fd,失败返回-1
int close(int fd);
根据open返回的文件描述符来关闭所打开的文件
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);
buf:缓冲区
这个缓冲区可以是用户手动在代码中定义的数组之类的东西,用于分批写入,累计到一定 数量/大小 再一次性写入,减少接口的使用次数
count:缓冲区大小
write:把内容拷贝到内存中的特定缓冲区中,而不是直接写入文件(磁盘/外设),什么时候把特定缓冲区中的内容刷新到文件/磁盘/外设由操作系统决定
read:不是直接访问磁盘的数据,而是把磁盘中的内容拷贝到内存的缓冲区中
以上两个缓冲区不是在调用函数时传入的buf,因为buf是用户定义的,而这里的缓冲区是系统早就规定好的
两者的返回值都是各自读写的字符个数
off_t lseek(int fd, off_t offset, int whence);
offset:偏移量
whence:偏移量的起始位置
SEEK_SET:文件开头
SEEK_CUR:当前位置
SEEK_END:文件末尾
该函数的作用是将文件指针移动到 whence + offset 的位置
int main() {
//设置当前函数中的umask
umask(0);
int fd = open(log, O_CREAT | O_WRONLY, 0666);
printf("fd: %d, errno: %d, errstring: %s\n", fd, errno, stringerror(errno));
const char* msg = "msg";
int cnt = 5;
while (cnt) {
//缓冲区
char line[128];
//往缓冲区中存数据
snprintf(line, sizeof(line), "%S, %d\n", msg, cnt);
//把缓冲区中的数据写入文件
write(fd, line, strlen(line)); //这里的strlen不用+1 -- \0作为分隔符是C语言的规定,不是文件的规定
}
//读取缓冲区
char buffer[1024];
//只能按个数读取,不能按行读取
ssize_t n = read(fd, buffer, sizeof(buffer) - 1); //注意:因为写入的时候不包含\0,所以读取的时候要留一个位置给\0
if (n > 0) {
buffer[n] = '\0';
printf("%s\n", buffer);
}
close(fd);
return 0;
}
任何一个进程在启动的时候都默认会打开三个文件:
1、标准输入:stdin、cin
2、标准输出:stdout、cout
3、标准错误:stderr、cerr
标准输出和标准错误都会向显示器打印,但是只有标准输出能重定向
文件描述符(open的返回值)的本质就是数组的下标:
PCB中有个结构体file_strcut用来存放该进程打开的文件的FCB,每个进程都有三个默认打开的文件,占用了0、1、2这三个下标,那么自己手动打开的文件下标就是从3开始(fd分配规则:最小的、未被使用的)
例如我们关闭了某个文件的标准输出流,那么1号fd就空出来了,那么下次open一个文件的时候这个文件的fd就是1(通过打开、关闭文件进行重定向)
原理:在上层无法感知的情况下,在OS内部改变进程对应文件描述符表中特定下标的指向
/a.out > log.txt -- 把1号文件(标准输出流)的内容重定向到log.txt中
./a.out > log.txt 2>&1 -- 把1号文件的内容重定向到log.txt中,同时把2号文件的内容重定向到目前的1号文件(log.txt)中
./a.out 1>log.txt 2>err.txt -- 把1号文件的内容重定向到log.txt中,把2号文件的内容重定向到err.txt中
之前的重定向都要关闭文件再打开(文件描述符总览的末尾有介绍),或者对可执行文件进行重定向(命令行重定向),有些不方便,dup函数可以直接对指定文件标识符进行覆盖
#include
int dup2(int oldfd, int newfd); -- 把old的内容拷给new(用old覆盖new),最终只剩下old文件描述符
//输出重定向
dup2(fd,1);