文件IO操作
文件描述符fd: 整型数,数组下标。文件描述符优先使用当前可用范围内最小的
- int open(const char *pathname, int flags);
- int open(const char *pathname, int flags, mode_t mode);
flags必须包含以下至少一个:O_RDONLY、O_WRONLY、O_RDWR
文件创建选项:
O_CREATE 有则清空、无则创建
O_TRUNC 截断
O_APPEND 追加
标准io | 文件io |
---|---|
r- | O_RDONLY |
r+ | O_RDWR |
w | O_WRONLY |
w+ | O_RDWR |
文件IO与标准IO的区别:
标准IO的吞吐量大(有缓冲机制)
系统IO的响应速度快 (是对程序而言,对用户而言stdio的速度“更快”)
注意:二者不可混用
文件IO与标准IO的转换:
- int fileno(FILE *stream); 转换出文件描述符
- FILE *fdopen(int fd, const char *mode); 转换出标准id
文件copy功能
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(int argc,char** argv)
{
if (argc < 3){
fprintf(stdout,"Usage...");
exit(1);
}
int sfd = open(argv[1],O_RDONLY);
if (sfd < 0){
strerror(errno);
exit(1);
}
int dfd = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600);
if(dfd < 0){
close(sfd);
strerror(errno);
exit(1);
}
const int SIZE = 1024;
char buf[SIZE];
while(1){
len = read(sfd,buf,SIZE);
if (len < 0){
strerror(errno);
break;
}
if (len == 0){
break;
}
//以防写入不足
while(len > 0){
int len = 0;//read的返回值
int ret = 0;//write的返回值
int pos = 0;//写截至的位置
ret = write(dfd,buf+pos,len);
if (ret < 0){
strerror(errno);
exit(1);
}
pos += ret;
len -= ret;
}
}
close(dfd);
close(sfd);
exit(0);
}
重定向
- int dup(int oldfd);
复制一个文件描述符(复制到可使用的(未使用的)最小新文件描述符) - int dup2(int oldfd, int newfd);
使newfd称为oldfd的副本,必要的话先close newfd,再把oldfd放到newfd。如果oldfd有效,且newfd == oldfd,dup2不操作,返回newfd
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#define FNAME "/tmp/out"
int main()
{
int fd;
fd = open(FNAME,O_WRONLY|O_CREAT|O_TRUNC,0600);
if (fd < 0) {
perror("open()");
exit(1);
}
//dup 不原子
close(1);//关闭标准输出
dup(fd);
close(fd);
/*********************/
printf("Hello world\n");
return 0;
}
将标准输出关闭后,文件描述符1空闲(不发生竞争时),dup将会把打开了文件/tmp/out的文件描述符复制给文件描述符1 ,之后对文件描述符1 的操作就相当与操作文件/tmp/out
#define FNAME "/tmp/out"
int main()
{
int fd;
fd = open(FNAME,O_WRONLY|O_CREAT|O_TRUNC,0600);
if (fd < 0) {
perror("open()");
exit(1);
}
//dup2 原子
dup2(fd,1);
if (fd != 1) {//打开的文件描述符如果不是1自己,就可以把他关掉了,有重定向后的 1 可以访问文件,保持尽量少的资源使用
close(fd);
}
/*********************/
printf("Hello world\n");
return 0;
}
同步
- sync 设备即将解除挂载时进行全局催促,将buffer cache的数据刷新
- fsync 刷新文件的数据
- fdatasync 刷新文件的数据部分,不修改文件元数据
补充
-
int fcntl(int fd, int cmd, … /* arg */ );
管理文件描述符
cmd:F_DUPFD、F_GETFD、F_GETFL -
int ioctl(int fd, unsigned long request, …);
管理设备 -
/dev/fd/目录 虚目录,显示当前进程文件描述符信息
-
truncate 把一个未打开的文件截断到多长
-
ftruncate 把一个已打开的文件截断到多长