【Linux】文件相关系统调用接口(IO)

早期在写C语言接口的时候,我们可以通过fopen来打开一个文件,下面这段两段代码为例:

hello.c写文件

  1 #include <stdio.h>                                                          
  2 #include <string.h>
  3  int main ()
  4 {
  5     FILE* fp=fopen("myfile","w");
  6     if(!fp){
  7         printf("fopen error!\n");
  8     }
  9     const char *msg="hello world!\n";
 10     int count = 5;
 11     while(count--){
 12         fwrite(msg,strlen(msg),1,fp);
 13     }
 14     fclose(fp);
 15     return 0;
 16 }

hello.c读文件

  1 #include <stdio.h> 
  2 #include <string.h>
  3  int main ()
  4 {
  5     FILE* fp=fopen("myfile","r");
  6     if(!fp){
  7         printf("fopen error!\n");
  8     }
  9     char buf[1024];
 10     const char *msg="hello world!\n";
 11     while(1){
 12         ssize_t s=fread(buf,1,strlen(msg),fp);
 13         if(s>0){
 14             buf[s]=0;
 15             printf("%s",buf);
 16         }
 17         if(feof(fp)){
 18             break;
 19         }
 20     }
 21     fclose(fp);
 22     return 0;
 23 }  

显而易见,是要往“myfile”文件中写五条“helloworld”,再通过读文件接口读出来。这里我们运用了fwrite、fread这些C语言接口。

 

如果我们想把一个字符串显示在显示器上,我们可以用 printf、putchar、fputchar、fputs、fprintf、fwrite.......等等一系列接口。而我们也知道任何一个进程在启动之后,默认打开三个输入输出流,分别为stdin、stdout、stderr,分别对应的设备是键盘、显示器、显示器。仔细观察发现,这三个流的类型都是FILE*,我们用fopen打开文件该返回值的类型就是FILE*。而这个FILE*是C语言提供的数据类型,所以说,这三个流与C语言强相关,都是C语言提供的接口。

 

这是我们的操作系统结构,通过这张图以及之前的知识我们知道,操作系统不会直接将自己的每个管理模块暴露出来给用户,而是通过一系列的系统调用接口。而刚刚提到的C语言提供的那些接口都是处于用户操作接口的lib中

但是刚才的代码表明我们最终将消息打印到了显示器上,即硬件。可是C库操作接口在上层的用户操作接口处,而硬件是在下面的硬件部分,所以说明我们必定要将要写入的数据自顶向下的交付给底层的硬件,但是要交付肯定不是C库直接去交付,因为我们没有这个权利,这就必定要通过操作系统来完成,也就是要通过系统调用接口。也就是说,我们的C库中,必定封装了对应的系统调用接口。

 

所以,我们现在可以以open为例看看系统调用接口,并且用系统调用接口来实现刚才的代码。

open

#include <sys/sypes.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname , int flags);
int open(const char *pathname , int flags , mode_t mode);

pathname: 要打开或创建的目标文件

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数:

O_RDONLY: 只读打开

O_WRONLY: 只写打开

O_RDWR : 读,写打开

这三个常量,必须指定一个且只能指定一个

O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限

O_APPEND: 追加写

返回值:

成功:新打开的文件描述符

失败:-1

类比C库调用接口,我们明白fopen底层必定调用了open。 下面用文件的系统调用接口来实现刚刚的代码

hello.c写文件

  1 #include <stdio.h>                                                          
  2 #include <string.h>
  3 #include <sys/stat.h>
  4 #include <sys/types.h>
  5 #include <unistd.h>
  6 #include <fcntl.h>
  7  
  8  int main ()
  9 {
 10     umask(0);//设置允许当前进程创建文件或者目录最大可操作的权限
 11     int fd = open("myfile",O_WRONLY|O_CREAT,0644);
 12     if(fd<0) {
 13         perror("open");
 14         return 1;
 15     }
 16     int count = 5;
 17     const char *msg = "hello world!\n";
 18     int len = strlen(msg);
 19     while (count--){
 20         write(fd,msg,len);//fd:文件描述符    msg:缓冲区首地址   len:本次读取期
                              望写入多少字节的数据       返回值:实际写了多少字节的数据
 21     }
 22     close(fd);
 23     return 0;
 24 }  

hello.c读文件 

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <sys/stat.h>
  4 #include <sys/types.h>
  5 #include <unistd.h>
  6 #include <fcntl.h>
  7  
  8  int main ()      
  9 {
 10     int fd = open("myfile",O_RDONLY);       
 11     if(fd<0) {    
 12         perror("open");      
 13         return 1; 
 14     }   
 15     const char *msg = "hello world!\n";    
 16     char buf[1024];          
 17     while(1){     
 18         ssize_t s=read(fd,buf,strlen(msg));//类比write
 19         if(s>0){  
 20             printf("%s",buf);
 21         }else{   
 22             break;
 23         }
 24     }
 25     close(fd);
 26     return 0;
 27 }

 

open、close、read、write、lseek 都属于系统提供的接口,称之为系统调用接口。所以,可以认为,f#系列的函数,都是对系统调用的封装,方便二次开发。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/Miss_Monster/article/details/86406503
今日推荐