文件描述符fd
文件描述符优先使用当前数组标记中小的去使用
在文件io中贯穿始终的类型
文件操作:
- open(const char* pathname, int flags); // 成功返回文件描述符,失败-1
cache是读的加速机制,buf是写的加速机制
man 2 open
该函数使用变参函数实现的,重载是定参实现,可变参数是变参实现的
宏 | 作用 | |
---|---|---|
o_rdonly | 只读 | r |
o_edwr | 读写 | r+ |
o_wronly | 只写 | w |
o_trunc | 截断,清空 | w |
o_create | 创建文件描述 | w |
o_nonblock | 非阻塞 | 能做就做,不能做就再等等 |
o_sync | 同步 |
- close(fd);
- read(int fd, void * buf, size_t count); 从文件描述符中读到buf中count个字节,返回读到多少个,失败返回-1,errno记录错误
- write(int fd, const void * buf, size_t count); 从buf写到fd中count个
- lseek(int fd, off_t offset, int whence); 对文件描述符定位
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char** argv)
{
if (argc < 3)
{
fprintf(stderr, "usage");
exit(1);
}
int srcfd;
int dstfd;
srcfd = open(argv[1], O_RDONLY);
if (srcfd < 0)
{
perror("open");
exit(1);
}
dstfd = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, 0600);
if (dstfd < 0)
{
close(srcfd);
perror("open");
exit(1);
}
#define SIZE 1024
char buf[SIZE];
int len;
int ret;
int pos = 0;
while (1)
{
len = read(srcfd, buf, SIZE);
if (len < 0)
{
// 读取出错
perror("read");
break;
}
else if (len == 0)
{
break;
}
while (len > 0)
{
// 信号可以打断系统调用,
ret = write(dstfd, buf + pos, len);
if (ret < 0)
{
perror("write()");
exit(1);
}
pos += ret;
len -= ret;
}
}
close(srcfd);
close(dstfd);
return 0;
}
将文件io与标准io区别
系统、文件io是调用一次,执行一次,马上进入内核操作,没有缓冲模式,—响应速度快
标准io是有缓冲区的----吞吐量大
一般情况下吞吐量—标准io更好
标准io和文件io不可混用
int fileno(FILE*); // 将FILE转换为文件描述符fd
FILE* fdopen(int fd, const int mode); 将文件描述符转成FILE*
strace 命令可以跟踪一个可执行文件的系统调用
time 命令可以测试一个可执行文件的运行时间
io的效率问题:
文件共享:
删除一个文件的第10行
lseek 11 + read + lseek + write
truncate(const char * path, off_t length); // 系统调用:未打开文件截断到长度
ftruncate(int fd, off_t length); // 将已经打开的文件截断到长度
原子操作:不可分割的操作,解决竞争和冲突
程序中的重定向:dup dup2
使用当前文件最小的文件描述符作为新的文件描述符,将原fd拷贝到新fd位置上
dup操作不是原子操作,将先关闭后赋值fd分开操作,会导致多进程编程出错
dup2(oldfd, newfd); // 是个原子操作
// 如果new和old相同,则dup2什么都不做
同步:sync fsync fdatasync
sync 同步缓冲区
fcntl(int fd , int cmd , …); 对文件描述符做cmd操作
ioctl(); 设备相关的内容
dup(fd)等效于fcntl(fd, F_DUPFD, 0);
dup2(fd, fd2)等效于 close();fcntl(fd,F_DUPFD, fd2);
/dev/fd/目录: 虚目录,显示当前文件描述符的信息
命令 ll /dev/fd