文件操作——C库调用与Linux系统调用区别

     Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions)。系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用的意思,面向的是硬件。而库函数调用则面向的是应用开发的,相当于应用程序的api,采用这样的方式有很多种原因,第一:双缓冲技术的实现。第二,可移植性。第三,底层调用本身的一些性能方面的缺陷。第四:让api也可以有了级别和专门的工作面向。


【库函数调用——缓冲文件系统】 

       缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用。

       当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读入接收的变量。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存 “缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器而定。

        缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据

       C库调用就是属于缓冲文件系统,例如:fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等是带缓冲的。


【系统调用——非缓冲文件系统】 
        非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它使用文件描述符来表示文件,只能读写二进制文件,但效率高、速度快。Linux系统调用就属于非缓冲文件系统,例如:open, close, read, write, getc, getchar, putc, putchar 等是不带缓冲的。

        文件描述符是一些小数值,你可以通过它们访问的打开的文件设备,而有多少文件描述符可用取决于系统的配置情况。但是当一个程序开始运行时,它一般会有3个已经打开的文件描述符,就是

0:标准输入

1:标准输出

2:标准错误

        那些数学(即0、1、2)就是文件描述符,因为在Linux上一切都是文件,所以标准输入(stdin),标准输出(stdout)和标准错误(stderr)也可看作文件来对待。


一、系统调用——非缓冲文件系统
A、open系统调用
open函数的原型为:

int open(const char *path, int oflags);
int open(const char *path, int oflags, mode_t mode);
参数说明:

path,是包括路径的完整文件名,

oflags是文件访问模式(即是什么方式打开文件,只读、只写还是可读并可写等),

mode用于设定文件的访问权限。具体的可选参数,可以自己查看手册页,这里不一一详述。

返回值说明:

         open建立了一条到文件或设备的访问路径,如果调用成功,返回一个可以被read、write等其他系统调用的函数使用的文件描述符,而且这个文件描述是唯一的,不与任何其他运行中的进程共享,在失败时返回-1,并设置全局变量errno来指明失明的原因。


B、write系统调用
write函数的原型为:

size_t write(int fildes, const void *buf, size_t nbytes);

函数说明:

        write的作用是把缓冲区buf的前nbytes个字节写入到 文件描述符fildes关联的文件中,返回实际写入的字节数。返回0表示没有写入任何数据,返回-1表示调用中出现了错误,错误代码保存在errno中。
注:fildes一定要是在open调用中返回的创建的文件描述符,或者是0、1、2等标准输入、输出或标准错误。

C、read系统调用
read函数的原型为:

size_t read(int fildes, void *buf, size_t nbytes);

函数说明:

        read系统调用的作用是从与文件描述符相关的文件里读入nbytes个字节的数据,并把它们放到数据区buf中,返回读入的字节数,失败时返回-1。

D、close系统调用
close调用的函数原型为:
int close(int fildes);

函数说明:

        close函数的作用是终于文件描述符fildes一其对应的文件之间的关联。


二、库函数调用——缓冲文件系统

A、fopen库函数
fopen库函数的原型为:
FILE* fopen(const char *filename, const char *mode);
函数说明:
       与底层系统调用open类似,成功时返回一个非空指针。失败时返回NULL。

B、fread库函数
fread库函数的原型为:
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);
函数说明:
      与底层调用read相似,其作用是从stream读取nitems个长度为size的数据到ptr所指向的缓冲区中。返回值是成功读到缓冲区中的记录个数。
注:stream为用fopen函数返回的文件结构指针。

C、fwrite库函数
fwrite库函数的原型:
size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);
函数说明:
       与底层调用write相似,其作用是从ptr指向的缓冲区中读取nitems个长度为size到数据,并把它们写到stream所对应的文件中。

D、fclose库函数
fclose库函数的原型为:
int fclose(FILE *stream);
函数说明:
       与系统调用close相似,其作用是关闭指定的文件流stream。

实例:

#include 
main() 
{ 
FILE *fp; 
char ch; 
if((fp=fopen("d:\\jrzh\\example\\c1.txt","rt"))==NULL) 
{ 
printf("\nCannot open file strike any key exit!"); 
getch(); 
exit(1); 
} 
ch=fgetc(fp); 
while(ch!=EOF) 
{ 
putchar(ch); 
ch=fgetc(fp); 
} 
fclose(fp);

附:

C库文件操作标准库函数汇总:

    文件的打开操作        fopen 打开一个文件  

    文件的关闭操作        fclose 关闭一个文件
                    
    文件的读写操作        fgetc 从文件中读取一个字符          

              fputc 写一个字符到文件中去   
              fgets 从文件中读取一个字符串   

              fputs 写一个字符串到文件中去
              fprintf 往文件中写格式化数据
              fscanf 格式化读取文件中数据
              fread 以二进制形式读取文件中的数据
              fwrite 以二进制形式写数据到文件中去
              getw 以二进制形式读取一个整数
              putw 以二进制形式存贮一个整数

     文件状态检查函数      feof 文件结束
              ferror 文件读/写出错
              clearerr 清除文件错误标志
              ftell 了解文件指针的当前位置

  文件定位函数              rewind 反绕
              fseek 随机定位


【区别】

1、本质:缓冲与非缓冲;

2、操作:系统调用通过文件描述符来操作文件,而库函数通过文件指针操作文件;

                系统调用只能以二进制的形式读写文件,而库函数可以以二进制、字符、字符串、格式化数据读写文件;

3、效率:系统调用效率更高。


你可能感兴趣的:(C/C++/Java)