上一篇提到两种对于文件的操作,一种是带缓冲区的(ANSI C),在用户态实现,流的相应资源也都存在与用户空间,无论使用那种缓冲区(全缓冲/行缓冲/无缓冲),最后一定还是会通过内核实现对文件的读写控制,因此在上一张说的fopen(),fclose(),fread(),fwrite()等必然调用了对操作系统的系统调用,而这些在这里对应为open(),close(),fread(),fwrite()。
文件操作:
1.打开文件:
open(文件路径,打开文件的方式即进程对该文件的访问权限,若有新文件创建决定新文件的权限......)成功则返回文件描述符
2.关闭文件:
close(调用open函数打开文件时返回的文件描述符)
3.创建文件:
creat(文件路径,文件权限)
这里open函数的第二个参数如果为O_CREAT,则可相当与creat函数使用
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <fcntl.h> 4 5 int main(int argc,char *argv[]) 6 { 7 int fd_open,fd_open_creat,fd_creat; 8 if((fd_open=open("test.txt",O_RDONLY))==-1) 9 { 10 perror("open"); 11 exit(EXIT_FAILURE); 12 } 13 printf("fd_open=open(...O_RDONLY)=%d\n",fd_open); 14 if((fd_open_creat=open("testnew.txt",O_CREAT|O_EXCL,0644))==-1) 15 { 16 perror("open"); 17 exit(EXIT_FAILURE); 18 } 19 printf("fd_open_creat=open(...O_CREAT|O_EXCL,0644)=%d\n",fd_open_creat); 20 if((fd_creat=creat("testcreat.txt",0644))==-1) 21 { 22 perror("open"); 23 exit(EXIT_FAILURE); 24 } 25 printf("fd_creat=creat(testcreat.txt,0644)=%d\n",fd_creat); 26 close(fd_open); 27 close(fd_open_creat); 28 close(fd_creat); 29 return 0; 30 }
4.文件控制:修改某文件的文件描述符
fcntl(想要修改文件的文件描述符,相应操作)
相应操作包括:file descriptor:F_DUPFD复制文件描述符,F_GETFD获得文件描述符,F_SETFD设置文件描述符,
file status flags:F_GETFL获得文件状态,F_SETFL设置文件状态(此时会有第三个参数表示将文件状态设置为什么)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <fcntl.h> 4 #include <sys/types.h> 5 6 int main(int argc,char *argv[]) 7 { 8 int accmode,val; 9 if(argc!=2) 10 printf("the argc must equal to 2"); 11 if((val =fcntl(atoi(argv[1]),F_GETFL,0))<0)//atio把字符串转换成长整型数 12 { 13 perror("fcntl"); 14 exit(EXIT_FAILURE); 15 } 16 printf("val:%d",val); 17 accmode=val&O_ACCMODE;//权限返回值,主要访问权限位低两位,用来测试权限 18 if(accmode==O_RDONLY) 19 printf("read only\n"); 20 else if(accmode==O_WRONLY) 21 printf("write only\n"); 22 else if(accmode==O_RDWR) 23 printf("read write\n"); 24 else 25 printf("unknown mode\n"); 26 if(val&O_APPEND) 27 printf(",append"); 28 if(val&O_NONBLOCK) 29 printf(",nonblocking"); 30 return 0; 31 } 32 ~
5.读写文件
read(要读取文件的路径,从文件路径读出的数据所放的位置--指针指向某内存空间,大小)
write(要写入文件的路径,数据存放的缓冲区buf---以buf为起始地址,数据大小)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <fcntl.h> 4 #include <string.h> 5 #include <sys/types.h> 6 7 int main(int argc,char *argv[]) 8 { 9 int fd_src,fd_des; 10 char buf[128]; 11 int num; 12 if(argc!=3) 13 { 14 perror("the format must be:cp file_src file_des "); 15 exit(EXIT_FAILURE); 16 } 17 if((fd_src=open(argv[1],O_RDONLY))==-1) 18 { 19 perror("open1"); 20 exit(EXIT_FAILURE); 21 } 22 if((fd_des=open(argv[2],O_CREAT|O_WRONLY|O_EXCL,0644))==-1) 23 { 24 perror("open2"); 25 exit(EXIT_FAILURE); 26 } 27 do{ 28 num =read(fd_src,buf,128); 29 write(fd_des,buf,num); 30 }while(num==128); 31 close(fd_src); 32 close(fd_des); 33 }
6.文件定位
通常指向文件头部,如果是以附加的方式打开则指向文件尾部,lseek则可以修改文件的读写位置
lseek(已经打开的文件,根据参考位置来移动读写位置的偏移数,参考位置)
参考位置包括:文件起始位置SEEK_SET,当前位置SEEK_CUR,结束位置SEEK_END
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <fcntl.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 7 char buf1[]="1234567890"; 8 char buf2[]="ABCDEFGHIJ"; 9 char buf3[]="abcdefghij"; 10 11 int main(int argc,char *argv[]) 12 { 13 int fd; 14 if((fd=creat("testlseek.txt",0644))<0) 15 { 16 perror("creat"); 17 exit(EXIT_FAILURE); 18 } 19 if(write(fd,buf1,10)!=10) 20 { 21 perror("write"); 22 exit(EXIT_FAILURE); 23 }//从文件起始处写buf1 24 if(lseek(fd,60,SEEK_SET)==-1) 25 { 26 perror("lseek"); 27 exit(EXIT_FAILURE); 28 }//从20处写buf2 29 if(write(fd,buf2,10)!=10) 30 { 31 perror("write"); 32 exit(EXIT_FAILURE); 33 } 34 if(lseek(fd,30,SEEK_SET)==-1) 35 { 36 perror("lseek"); 37 exit(EXIT_FAILURE); 38 } 39 if(write(fd,buf3,10)!=10) 40 { 41 perror("write"); 42 exit(EXIT_FAILURE); 43 }//从10位置写buf3 44 return 0; 45 }
7.映射文件到内存
将某个文件的指定内容映射到内存空间中,提供不同于一般文件的读写访问方式,进程可以像读写内存一样读写文件,而不必再调用read(),write()等操作,函数将在进程的虚拟地址空间与文件描述符关联的文件之间建立映射
mmap(映射的特定地址——一般情况下为null由系统分配,映射的文件长度,映射的内存权限,控制程序对内存段的改变造成的影响,映射的文件描述符,偏移——映射内容在该文件中的起始位置)
mmap(null,length,pro,flags,fd,offset)
例子:磁盘按块的方式读写,因此想要在磁盘文件中的某个位置插入内容是比较困难的,因为会覆盖掉插入部分后面的内容,就可以用映射将整个文件映射到内存,访问速度提高,获得插入内容以及插入位置,把文件的内容向后移动相应大小,写入要插入的内容之后再写回磁盘
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <fcntl.h> 4 #include <unistd.h> 5 #include <string.h> 6 #include <sys/mman.h> 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 10 int main(int argc,char *argv[]) 11 { 12 int fd; 13 int length; 14 int pagesize=0; 15 char *mapped_mem;//存储页大小 16 pagesize=getpagesize(); 17 fd=open(argv[1],O_RDONLY|O_CREAT,S_IRESR|S_IWUSR); 18 length=lseek(fd,0,SEEK_END);//得到文件长度 19 lseek(fd,(pagesize*2-length%pagesize-1),SEEK_END);//在后面添加空闲空间,大小为1-2倍页的大小 20 write(fd,"-1",1);//写一个内容,否则mmap不到添加的新空间 21 mmaped_men=mmap(null,length/pagesize+2,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); 22 printf("\npls input info you insert(size<%d):",length); 23 int local=0; 24 scanf("%d",&local); 25 memmove(mapped_mem+local,buf,strlen(buf),mapped_mem+local,length-local);//移动要添加位置后面的所有信息 26 memcpy(mapped_mem,buf,strlen(buf)-1); 27 msync(mapped_mem,length/pagesize+2,MS_SYNC|MS_INVALIDATE); 28 munmap(mapped_mem,length/pagesize+2); 29 ftruncate(fd,length+strlen(buf)); 30 return 0; 31 }