文件io
操作系统为了方便用户使用系统功能而对外提供的一组系统函数。称之为 系统调用(systemcall)
c库是为了通用(跨平台,linux,win ),而设计的函数接口。
systemcall 直接可以使用linux系统提供的功能。 c库是对 systemcall 的封装。c库的函数会调用
systemcall中的函数
标准io 文件io的区别
.1 没有缓存区 , 文件io更适合操作 设备文件。
.2 操作对象不在是文件流指针,而是文件描述符(很小的非负的整数 0-1023 )
每个程序在启动的时候操作系统默认为其打开
三个描述符与流对象匹配:
0 >STDIN_FILENO = stdin
1 >STDOUT_FILENO == stdout
2 ==>STDERR_FILENO == stderr
stdin,stdout,stderr,=>FILE
open是最底层内核调用,内核只使用整数fd来标识打开的文件;
FILE* 是C标准库在fd外面额外套的一层包装,只有fopen这套标准IO才会用到FILE*
open
1 int open(const char *pathname, int flags, int mode);
2 功能:
3 获得一个文件描述符
4 参数:
5 pathname:文件名
6 flags:
7 O_RDONLY 只读
8 O_WRONLY 只写
9 O_RDWR 又读又写
10 O_CREAT,创建文件
11 O_EXCL,需要和O_CREAT同时使用,表示新建的文件不能存在,否则open就会失败
12 O_NOCTTY,不是终端设备
13 O_TRUNC文件内容清空
14 O_APPEND追加
15 O_ASYNC异步io,什么时候io不确定。
16 O_NONBLOCK非阻塞
18 返回值:
19 成功返回文件描述符
20 失败返回-1
使用如下
#include <stdio.h> #include<sys/types.h> //定义mode_t等基础类型 #include<sys/stat.h> //文件权限相关 #include<fcntl.h> //放open原型,O_RDONLY/O_CREAT这些宏 int main(int argc, char **argv) { int num = 1280323; int fd = open("1.txt",O_WRONLY|O_CREAT|O_TRUNC,0666); if(-1 == fd) { printf("open error\n"); return 1; } return 0; }理解 按位或的原因是他们本质都是单个bit置1的整数宏,每个功能都要使用所以这样,可以当成只写的固定搭配
O_WRONLY → 0000 0001
O_CREAT → 0000 0010
O_TRUNC → 0000 0100
0666来源
权限分3类人:所有者、同组、其他人
权限值:
- 4 = r 读
- 2 = w 写
- 1 = x 执行
6 = 4 + 2 → r w,没有执行权限
所以一个6 = rw-
0666拆开:
- 第一个6:所有者 → rw-
- 第二个6:同组用户 → rw-
- 第三个6:其他人 → rw-
前面的0:代表这是八进制数(C语言里以0开头代表八进制)
所以 0666 = rw-rw-rw-
写出来是0666,但是实际上效果是0664(因为这是给各种访问者设置权限,所以有 O_CREAT,才要权限;没有 O_CREAT,不要 0666)
umask = 0002(最常见默认值)
umask 含义:要屏蔽掉、取消掉的权限
umask 0002 → 取消「其他用户的写权限」
目标权限: 0666
~umask:把umask按位取反 → ...(~0002)111 111 101 & 110 110 110 (0666)
结果:0664 ,权限 rw-rw-r--
write
1 size_t write(int fd, const void *buf, size_t count);
2 功能:
3 通过文件描述符向文件中写一串数据
4 参数:
5 fd:文件描述符
6 buf:要写入文件的数据的首地址
7 count:要写入字符的个数(buf中实际内容的长度)
8 返回值:
9 成功返回实际写入的个数
10 失败返回-1
write使用例子
#include <stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> //write,read,close函数的头文件 #include<string.h> int main(int argc, char **argv) { int num = 1280323; int fd = open("1.txt",O_WRONLY|O_CREAT|O_TRUNC,0666); if(-1 == fd) { printf("open error\n"); return 1; } char buf[256] = "hello,are you"; write(fd,buf,strlen(buf)); return 0; }read
1 size_t read(int fd, void *buf, size_t count);
2 功能:
3 通过文件描述符从文件读取一串数据
4 参数:
5 fd:文件描述符
6 buf:存放读到数据的缓冲区首地址
7 count:想要读取的字节个数
8 返回值:
9 成功返回读到的字节个数
10 读到文件末尾返回0
11 失败返回-1
read使用例子
#include <stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<string.h> int main(int argc, char **argv) { int num = 1280323; int fd = open("1.txt",O_RDONLY); if(-1 == fd) { printf("open error\n"); return 1; } while(1) { char buf[256] = {0}; int ret = read(fd,buf,sizeof(buf)); if(ret <= 0) { break; } printf("ret is %d,buf:[%s]\n",ret,buf); } close(fd); return 0; }lseek
1 off_t lseek(int fd, off_t offset, int whence);
2 功能:
3 定位光标的位置
4 参数:
5 fd:文件描述符
6 offset:偏移量
7 正:向后偏移
8 负:向前偏移
9 零:不偏移
10 whence:
11 SEEK_SET
12 SEEK_CUR
13 SEEK_END
14 返回值:
15 成功返回偏移量
16 失败返回-1
lseek使用例子
#include <stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<string.h> int main(int argc, char **argv) { int fd = open("1.txt",O_RDONLY); if(-1 == fd) { printf("open error\n"); return 1; } off_t off = lseek(fd,0,SEEK_END); printf("size is %ld\n",off); lseek(fd,0,SEEK_SET); char c = 0; read(fd,&c,1); printf("%c\n",c); close(fd); return 0; }