im6ull学习归纳总结(一)APP——04_文件IO
4.1文件从何而来
如图所示文件可以是
1真实文件保存在设备上
2内核提供的虚拟文件
3设备节点
4.2文件的访问方式
4.2.1通用IO模型:open/read/write/lseek/close
实验1 copy文件
代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(char argc, char **argv)
{
int fd_old ,fd_new;
char buf[1024];
int len;
if (argc != 3)
{
printf("Usage: %s <old-file> <new-file>",argv[0]);
return -1;
}
fd_old = open(argv[1],O_RDONLY);
if (fd_old == -1)
{
printf("can not open file %s\n",argv[1]);
return -1;
}
/*open函数用于打开 创建 文件
O_WRONLY 只写方式
O_CREAT如果文件不存在则创建文件
O_TRUNC如果文件已经存在则截断文件(截断就是将文件大小设置为0清空文件)
S_IRUSR这里分别表示设置用户(owner)具有读取权限 USR是设置用户OWNER
S_IWUSR这里分别表示设置用户(owner)具有写权限
S_IRGRP组具有读取权限
S_IWGRP组具有写权限 GRP是组
S_IROTH其他用户有读权限
S_IROTH其他用户有写权限 OTH是其他
*/
fd_new = open(argv[2],O_WRONLY |O_CREAT |O_TRUNC,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWGRP | S_IROTH | S_IWOTH);
if(fd_new==-1)
{
printf("can not creat file %s \n",argv[2]);
return -1;
}
/* read函数 参数1 要读取的文件描述符或套接字
参数2 读取数据的缓冲区指针
参数3 要读取的字节数
read 函数的返回值 成功读取返回读取的字节数
读完到达文尾 返回0
发生错误翻入-1
*/
/* 当返回0时读完跳出循环 */
while ((len = read(fd_old,buf,1024))>0)
{
if(write(fd_new,buf,len)!=len)
{
printf("can not write %s\n",argv[2]);
return -1;
}
}
close(fd_old);
close(fd_new);
return 0;
}
实验现象
完成复制
这里逻辑简单
终端中参数 不为3 打印用法否则正常运行
这里注意
read 函数从文件中读取数据,它并不关心文件的读取位置(file offset)。文件的读取位置是由文件描述符(file descriptor)维护的,而不是由 read 函数控制。
当你打开一个文件时,文件描述符的读取位置通常位于文件的开头,但每次读取操作后,文件描述符的读取位置都会根据已读取的字节数进行移动。这是因为文件描述符会跟踪已读取的字节数,以便下一次读取可以继续从上次读取结束的地方开始。
文件描述符中包含一个文件偏移量(file offset)的信息,该偏移量表示下一次读写操作将在文件中的哪个位置发生。文件描述符的文件偏移量是由系统内核维护的,它跟踪文件中的当前位置。每个进程的每个文件描述符都有自己的文件偏移量。
当你打开文件时,文件偏移量通常被设置为文件的开头。每次读取或写入操作完成后,文件偏移量都会相应地被更新,以指示下一次读写将从哪里开始。
文件描述符的值并没有变
文件描述符 (fd) 是一个整数值,它在文件的生命周期内保持不变。在文件打开时,文件描述符被分配,它代表了一个与文件相关联的资源。这个值在文件打开时被设置,并且在关闭文件时被释放。
非通用函数 ioctl、mmap
用mmap实现文件复制
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
int main(char argc, char **argv)
{
int fd_old,fd_new;
struct stat stat;
char * buf;
if(argc != 3)
{
printf("Usage:%s <old_file> <new_file>\n",argv[0]);
return -1;
}
fd_old = open(argv[1],O_RDONLY);
/* 打开旧文件 */
if(fd_old==-1)
{
printf("can not open file %s\n",argv[1]);
return -1;
}
/* fstat 获取fd_old文件信息并保存在stat结构体中*/
if (fstat(fd_old,&stat)==-1)
{
printf("can not get stat of file %s \n",argv[1]);
return -1;
}
/* 将描述符为fd_old的文件映射到虚拟内存上
NULL为映射内存首地址由系统自动分配
stat.st_size,映射区大小也是文件大
PROT_READ表示对该区域的访问为只读权限
MAP_SHARED表示其他进程也可以共享该区域的内容
mmap函数返回的是映射区域的起始地址
这样先将old文件映射到虚拟内存上,将虚拟内存的首地址给buf,再从buf的首地址开始将值写入new文件中*/
buf = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd_old, 0);
if (buf == MAP_FAILED)
{
printf("can not mmap file %s\n",argv[1]);
return -1;
}
fd_new = open(argv[2],O_WRONLY | O_CREAT | O_TRUNC,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fd_new == -1)
{
printf("can not creat file %s\n",argv[2]);
return -1;
}
if (write(fd_new,buf,stat.st_size)!=stat.st_size)
{
printf("can not write %s \n",argv[2]);
return -1;
}
close(fd_new);
close(fd_old);
return 0;
}
现象:
文件已经被复制了
查看函数用法的方法
help 用于查看命令用法
ls --help查看ls命令用法
info 查看命令、函数的具体用法
例如 info ls
info open
man man 相当于比info简单
例如 man ls
man open
基本用man
系统调用函数进入内核的过程
我们程序中调用的open read write 函数是用户态调用的API
内核sys_open、sys_read的作用
进入内核后,sys_read/open 会首先根据参数判断文件的类型,然后根据不同的文件类型去找不同的设备驱动,继而进行读写或者输入输出控制
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!