Linux系统调用和ANSI C文件操作的区别
一、在Linux下对文件操作有两种方式:Linux系统调用和ANSI C文件操作。
1、Linux系统调用调用常用于I/O文件操作,系统调用常用的函数有open、close、read、write、lseek、ulink等。
2、 ANSI C文件操作
ANSI C文件操作方法是所有操作系统通用的文件操作方法,它的操作是被缓冲过的被修改的文件并不会立即反应到磁盘中,它在内存中开辟一个“缓冲区”,为程序中的每一个文件操作所使用,当执行读文件的操作时,从磁盘文件中将数据先读入内存“缓冲区“,装满后再从内存“缓冲区”依次读入接收的数据。这种文件操作方式又被称作流式文件操作。ANSI C文件操作常用的函数有fopen、fclose、fread、fwrite、fseek、ftell、rewind、fgetc、fputc、fgets、fputs及remove等
三、下面用两个函数说明Linux系统调用和ANSI C文件操作的区别。
1、由于缓冲区的存在,因此流中的数据与对应文件的数据可能不一致,当系统掉电时,文件若没有及时close(),缓冲区的数据就会丢失,为了同步缓冲区,此时可以调用fflush()函数实现。
fflush()函数需要的头文件:
#include <stdio.h>
函数原型:
int fflush(FILE *stream);
参数说明:
stream:文件句柄。
返回值:
成功返回0;
失败返回EOF。
应用示例:
fflush函数应用示例代码如程序清单1所示。示例程序用来用while死循环模拟掉电状态,打开或创建当前目录下的“./test_2”文件并写入“Hello,world!”字符串。当调用fflush函数后,文件成功写入“Hello,world!”字符串,否则将未写入该字符串。
程序清单1
#include <stdio.h>
#define SyncTestOn 0
int main(void)
{
FILE *fp;
int iCount;
char *str = "Hello world!";
fp = fopen("./test_2", "w"); // 打开文件以获得操作该文件的句柄
iCount = fwrite(str, 12, 1, fp);
printf("%d block(12 bytes per block) read, check it out!\n", iCount);
if (SyncTestOn) {
fflush(fp);
while(1);
} else {
while(1);
}
fclose(fp);
}
说明:SyncTestOn 为0时,程序没有调用fflush(),运行e10时,程序进入while循环,用“Ctrl”+“C”强制退出程序(模拟掉电状态),用cat test_2命令查看文件,数据此时并没有写入;SyncTestOn 为1时,程序调用fflush(),运行e10,程序进入while,用“Ctrl”+“C”强制退出程序,然后用cat test_2查看文件,数据此时已经写入。
2、由于缓冲区的存在,为了同步缓冲区,可以调用fflush()实现。但是当掉电时,未调用fflush()时,此时缓冲区的数据仍旧会丢失。而setvbuf()函数可以修改缓冲区的工作模式,也可以解决这一问题。
setvbuf函数需要的头文件:#include <stdio.h>函数原型:int setvbuf(FILE *stream,char *buf,int mode,size_t size);
参数说明: stream:文件句柄。 buf:如果buf未NULL,由编译器决定如何建立流的缓冲区,否则其应该指向一段大小为size的内存。 mode:指定了缓冲区的类型,_IOFBF(全缓冲),_IOLBJ(行缓冲),_IONBF(无缓冲)。
size:指定了缓冲区的大小。如果指定一个不带缓冲区的流,则忽略 buf 和 size 参数。返回值: 成功返回0; 失败返回非零值。
应用示例:setvbuf函数应用示例代码如程序清单2所示。
示例程序用来用while死循环模拟掉电状态,打开或创建当前目录下的“./test_3”文件并写入“Hello,world!”字符串。当调用setvbuf函数将缓冲区的类型设置为_IONBF后,文件可以正常写入“Hello,world!”字符串,否则将未写入该字符串。
<pre name="code" class="cpp">#include <stdio.h>
#define SycnTestOn 1
int main(void)
{
FILE *fp;
int iCount;
char *str = "Hello world!";
fp = fopen("./test_3", "w"); // 打开文件以获得操作该文件的句柄
if(Sycn_Test_On){
setvbuf(fp,NULL,_IONBF,0);
}
iCount = fwrite(str, 12, 1, fp);
printf("%d block(12 bytes per block) read, check it out!\n", iCount);
while(1);
fclose(fp);
}
说明:测试方法同fflush()一致;setvbuf()函数如果要设置流的缓冲区,则函数必须在打开文件后立即调用,一旦操作了流,就不能再调用此函数了,否则结果不可预知。非缓冲的文件操作访问方式,每次对文件进行一次读写操作时,都需要使用linux系统调用来处理此操作,执行一次linux系统调用将涉及到CPU状态的切换,即从用户空间切换到内核空间,实现进程上下文的切换,这将损耗一定的CPU时间,频繁的磁盘访问对程序的执行效率会造成较大的影响。
除此以外,setbuf也可以实现setvbuf用法,
需要的头文件:
#include <stdio.h>函数原型:
int setbuf(FILE *stream,char *buf);
参数说明:
stream:文件句柄。
buf:参数buf须指向一个长度为BUFSIZ的缓冲区,如果将buf设置为NULL,则
关闭缓冲区。
返回值:
成功返回0;
失败返回非零值。
四、通过以上内容,总结Linux系统调用和ANSI C文件操作的区别。
1、 Linux系统调用
Linux系统调用实际上就是指最底层的一个调用,在linux程序设计里面就是底层调用,面向的是硬件。而ANSI C则是库函数调用,是面向的是应用开发的,相当于应用
程序的API(应用程序接口)。我觉得采用这样的方式有以下几个原因:
第一,双缓冲技术的实现;
第二,可移植性的考虑;
第三,底层调用本身的一些性能缺陷(如频繁擦写影响文件存储介质的寿命);
第四,让API也可以有具体分层和专门的应用方向。
Linux系统调用是操作系统相关的,因此一般没有跨操作系统的可移植性。Linux系统调用发生在内核空间,因此如果在用户空间的一般应用程序中使用系统调用来进行文件操作,会有用户空间到内核空间切换的开销。
事实上,即使在用户空间使用ANSI C文件操作,因为文件总是存在于存储介质上,因此不管是读写操作,都是对硬件(存储器)的操作,都必然会引起Linux系统调用。也就是说,ANSI C文件操作实际上是通过系统调用来实现的。例如C库函数fwrite()就是通过write()系统调用来实现的。这样的话,使用库函数也有系统调用的开销,为什么不直接使用系统调用呢?这是因为读写文件通常是大量的数据(这种大量是相对于底层驱动的系统调用所实现的数据操作单位而言),这时,使用ANSI
C文件操作就可以大大减少系统调用的次数。这一结果又缘于缓冲区技术。在用户空间和内核空间,对文件操作都使用了缓冲区,例如用fwrite写文件,都是先将内容写到用户空间缓冲区,当用户空间缓冲区满或者写操作结束时,才将用户缓冲区的内容写到内核缓冲区,同样的道理,当内核缓冲区满或写结束时才将内核缓冲区内容写到文件对应的硬件媒介。
2.4.2 ANSI C文件操作
ANSI C文件操作通常用于应用程序中对一般文件的访问。ANSI C文件操作是系统无关的,因此可移植性好,由于ANSI C文件操作是基于C库的,因此也就不可能用于内核空间的驱动程序中对设备的操作。
Linux系统调用和ANSI C文件操作的区别的更多相关文章
- Linux C 下的大文件操作
这里说的大文件指大小超过4G的文件. 在32位环境下,linux默认打开.读.写超过4G的文件会返回错误.定义如下宏可以突破这个限制,对read/write和fread/fwrite同时有效. 注意它 ...
- [Linux]目录x权限对文件操作的影响
问题 我们常使用linux以下命令 cd 进入目录 ls 列出目录中的文件 或者直接打开目录中的文件 以上操作对于目录权限位的设置来说,是有一定迷惑性的,如表格所示 cd进入该目录 cd进入该目录 ...
- linux系统调用、库函数和内核函数关系与区别
看系统调用,还有库函数,以前一直不明白,总是以为 系统调用跟库函数是一样的,但是今天才知道是不一样的. 库函数也就是我们通常所说的应用编程接口API,它其实就是一个函数定义,比如常见read().wr ...
- Linux程序设计 读笔3 文件操作
一 linux文件结构 二 系统调用和设备驱动程序 三 库函数 四 底层文件访问 五 标准IO库 六 格式化输入输出 七 文件和目录的维护 八 扫描目录 九 错误处理 十
- Linux常用命令_(文件操作)
对文件的操作主要有以下命令: touch.cp.rm.mv.ln.mkdir.rmdir
- linux命令(5)文件操作:ls命令、显示文件总个数
一:ls命令是最常用的linux命令了:下面是ls --help里面的用法 在提示符下输入ls --help ,屏幕会显示该命令的使用格式及参数信息: 先介绍一下ls命令的主要参数: -a 列出目录下 ...
- Linux下C语言的文件操作
代码: #include <stdio.h> #include <string.h> #include <fcntl.h> /*************基本的函数A ...
- Linux基础第四课——文件操作
文件的创建 touch sudo touch 文件1 文件2 文件3 #支持批量创建文件 sudo rm -f 文件1 文件2 文件3 #支持批量创建 也支持批量删除 echo '谁动谁输,对不起我输 ...
- linux下c/c++的文件操作
opendir,readdir,closedir, stat()查询文件状态 open(), O_TRUNC这个Flag会把打开的文件清零... 文件锁:fcntl, F_GETLK , F_SETL ...
随机推荐
- Typora + Powershell/bash + Git搭建自己的笔记
网上都说什么onenote,evernote,ant等笔记.个人感觉这些都不算太好,还是自己用简易东西搭建一个笔记. 个人推荐使用typora写笔记. 上面既有文件目录,还能通过模糊搜索. 然后需要p ...
- css中height, width默认值
转载自:https://www.cnblogs.com/heyode/p/5973960.html <body> <div class="wrap"> &l ...
- ubuntu下安装perl GD模块
依次执行: sudo apt-get install libgd2-xpm-dev sudo perl -MCPAN -e shell install Bundle::CPAN install GD: ...
- 设置TextField的响应View和toolBar
inputView 设置用于展示的响应View 类似于键盘的展示方式 inputAccessoryView 用于设置响应View上面的ToolBar 使用方式: inputView设置为响应View ...
- poj1386有向图判断是否存在欧拉回路或者欧拉路
有向图的图联通是指基图联通,也就是把有向图的边改成无向图然后看是否连通.判断联通可用dfs或者并查集. 题意就是给你n个由小写字母构成的字符串,问你能不能将这n个字符串连接起来,B能接在A后面的条 ...
- 【python 】文件下载进度条(装逼利器)
基础版 import requests url = "http://mp.111ttt.cn/mp3free/81135985.mp3" rsp = requests.get(ur ...
- 织梦系统dedecms实现列表页双样式,列表样式循环交替变化
有时候做列表页需要交替变换样式,那如何实现列表页双样式呢? 在DeDeCMS里面有这样一个函数,可以循环赋予html代码不同的样式,如下: [field:global function=MagicVa ...
- axios发送post form请求
axios发送post form请求 只需修改url和data即可 axios({ url: '/user', method: 'post', data: { firstName: 'Fred', l ...
- ES6-变量let和常量const
1.以往js变量 var 1.可以重复声明 2.无法限制修改(指不能声明常量) 3.没有块级作用域(指{}这样的) 2.现在ES6变量 let 不能重复声明-变量,可以修改,块级作用域 const 不 ...
- PowerPC-MPC56xx Flash模式代码启动过程
https://mp.weixin.qq.com/s/iruM5VwKgnH_7nmIQxO0-g 参考第5章 In order for the e200z4d core to be able ...