文件IO
应用层 ,内核层,硬件层
Input Output
所谓输入输出是站在应用层来看的,所谓输入就是内核输入到应用,输出指用户数据传到内核。输入输出涉及到文件IO。
open
打开或创建一个文件。
//在fcntl.h文件中声明。函数作用:创建或打开某一个文件。
/**
第一个参数:char* 包含有文件名和路径
第二个参数:打开文件的方式
flag:
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
O_CREAT 创建一个文件
O_EXIT 如果使用O_CREAT时文件存在,则可返回错误信息,
这一参数可以测试文件是否存在
O_TRUNC 打开文件(会把已经存在内容删除)
O_APPEND 追加方式打开(不会把已经存在的东西删除)
第三个参数:创建文件的权限
文件最终权限 =mode &(~umask)
umask获取:终端中输入命令 umask
返回值:
成功:文件描述符,他是一个非负的正整数,即文件的ID号
错误:-1
文件描述符:内核的一个重要功能是文件管理,系统有非常多的文件,内核怎样
认识每一个文件呢?内核采用ID号的方式标识这些文件,inode号表示不同的文件,比如ls -lai i 只要文件不一样inode号就不一样
open函数创建成功文件描述符从3开始。
因为一个进程打开的时候,内核会自动打开三个文件描述符:0,1,2
*/
open(char*,flag,mode)
案例——open和close实现touch命令
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int args,char *argv[]){
int fd;
fd = open(argv[1],O_CREAT|O_RDWR,0777);
if(fd<0){
printf("create file %s failure\n",argv[1]);
return -1;
}
printf("create file %s sucess %d\n",argv[1],fd);
close(fd);
return 0;
}
使用gcc -o touch a.c
得到一个可执行文件touch
执行./touch b.c 就会创建一个b.c文件
read
内核向应用层写数据
第一个参数:从哪一个文件读
第二个参数:读到什么地方去
第三个参数:读多少个
返回值:实际读到的字节数
read(int fd,void *buf, size_t count)
write
应用层向内核层写数据
第一个参数:向哪一个文件中去写
第二个参数:想这个文件中写什么
第三个参数:想这个文件中写多少
返回值:实际所写的字节数
write(int fd, void *buf, size_t count)
close
关闭当前正在操作的文件,释放内核空间
lseek
调整文件指针
该函数申明在sys/types.h
第一个参数:要调整的文件的文件指针
第二个参数:偏移量,每一次读写所需要移动的距离,单位是字节的数量,可以正负(向前移动,向后移动)
第三个参数:当前位置的基点,有三个标志
SEEK_SET:当前位置为文件开头,新位置为偏移量的大小
SEEK_CUR:当前位置的文件指针的位置,新位置为当前位置加上偏移量
SEEK_END:当前位置为文件结尾,新位置为文件的大小加上偏移量的大小
返回值:
成功:文件当前位置
错误:-1
lseek(int fd, off_t offset, int whence)
案例——CP命令实现
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int args, char *argv[]){
int r_fd,w_fd;
char red_buf[128] = {0};
int rd_ret = 0;
if(args < 3){
printf("plese int put src file and des file\n");
return -1;
}
r_fd = open(argv[1],O_RDONLY);
if(r_fd<0){
printf("open src file %s failure\n",argv[1]);
return -2;
}
printf("open src file %s success,r_fd=%d\n",argv[1],r_fd);
w_fd = open(argv[2],O_WRONLY);
if(w_fd<0){
printf("open des file %s failure\n",argv[2]);
return -3;
}
printf("open des file %s success,w_fd%d\n",argv[2],w_fd);
while (1)
{
rd_ret = read(r_fd,red_buf,128);
if (rd_ret<128)
{
/* code */
break;
}
write(w_fd,red_buf,rd_ret);
memset(red_buf,0,128);
}
write(w_fd,red_buf,rd_ret);
close(r_fd);
close(w_fd);
return 0;
}
编译之后。在该文件夹下新建一个文件aa.c。
使用编译过后的命令将a.c的内容拷贝到aa.c文件中