当前位置: 技术问答>linux和unix
fwrite()库函数为什么会吃内存?
来源: 互联网 发布时间:2016-05-10
本文导语: 以前没有注意这个问题,偶然发现自己的内存呼呼地往下降,最后定位在fwrite()函数上。 现象是这样的: 比如写一个300K的文件,内存就减少300K,直到减至一个稳定的值。(8M左右,我这里用的是128M的内存) fwrite...
以前没有注意这个问题,偶然发现自己的内存呼呼地往下降,最后定位在fwrite()函数上。
现象是这样的:
比如写一个300K的文件,内存就减少300K,直到减至一个稳定的值。(8M左右,我这里用的是128M的内存)
fwrite()调用成功返回后也不释放内存,除非我的程序停掉。
这是为什么呀,大家在写程序的时候,特别在写大文件的时候是像我这样
fwrite(buffer,1,size,pFILE);这样使用还是有其他技巧?
现象是这样的:
比如写一个300K的文件,内存就减少300K,直到减至一个稳定的值。(8M左右,我这里用的是128M的内存)
fwrite()调用成功返回后也不释放内存,除非我的程序停掉。
这是为什么呀,大家在写程序的时候,特别在写大文件的时候是像我这样
fwrite(buffer,1,size,pFILE);这样使用还是有其他技巧?
|
这应该是一个操作系统调度问题,而不是一个编程问题,我在Linux内核2.6.9(内存256MB)下做了测试:
按照LZ的那种写文件方式,确实有这个现象,不过top监控是进程本身的虚拟内存和物理内存消耗很少,基本很稳定,但是vmstat跟踪系统状态结果如下
[root@localhost ~]# vmstat 60
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
2 0 224 116320 4780 35520 0 0 59 125 537 216 3 5 91 1
0 0 224 94288 5096 57304 0 0 0 371 1072 486 5 6 88 1
0 0 224 70192 5432 81148 0 0 0 418 1057 351 2 3 95 0
0 0 224 46312 5764 104736 0 0 0 412 1058 326 1 3 96 0
0 0 224 21892 6284 128656 0 0 8 430 1071 395 2 3 94 1
0 0 224 18156 5264 133056 0 0 47 414 1087 531 3 4 91 1
0 0 224 17312 5284 133816 0 0 1 421 1132 574 3 4 92 0
0 0 224 18620 5252 132288 0 0 0 417 1058 372 2 3 95 0
可以看到memory下free和cache的变化趋势(间隔60秒),也就是系统空闲内存都用来做cache了,以提高写入磁盘的性能
从http://www.faqs.org/docs/linux_admin/buffer-cache.html摘录部分段落也说明了该问题
If the cache is of a fixed size, it is not very good to have it too big, either, because that might make the free memory too small and cause swapping (which is also slow). To make the most efficient use of real memory, Linux automatically uses all free RAM for buffer cache, but also automatically makes the cache smaller when programs need more memory.
Under Linux, you do not need to do anything to make use of the cache, it happens completely automatically. Except for following the proper procedures for shutdown and removing floppies, you do not need to worry about it.
按照LZ的那种写文件方式,确实有这个现象,不过top监控是进程本身的虚拟内存和物理内存消耗很少,基本很稳定,但是vmstat跟踪系统状态结果如下
[root@localhost ~]# vmstat 60
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
2 0 224 116320 4780 35520 0 0 59 125 537 216 3 5 91 1
0 0 224 94288 5096 57304 0 0 0 371 1072 486 5 6 88 1
0 0 224 70192 5432 81148 0 0 0 418 1057 351 2 3 95 0
0 0 224 46312 5764 104736 0 0 0 412 1058 326 1 3 96 0
0 0 224 21892 6284 128656 0 0 8 430 1071 395 2 3 94 1
0 0 224 18156 5264 133056 0 0 47 414 1087 531 3 4 91 1
0 0 224 17312 5284 133816 0 0 1 421 1132 574 3 4 92 0
0 0 224 18620 5252 132288 0 0 0 417 1058 372 2 3 95 0
可以看到memory下free和cache的变化趋势(间隔60秒),也就是系统空闲内存都用来做cache了,以提高写入磁盘的性能
从http://www.faqs.org/docs/linux_admin/buffer-cache.html摘录部分段落也说明了该问题
If the cache is of a fixed size, it is not very good to have it too big, either, because that might make the free memory too small and cause swapping (which is also slow). To make the most efficient use of real memory, Linux automatically uses all free RAM for buffer cache, but also automatically makes the cache smaller when programs need more memory.
Under Linux, you do not need to do anything to make use of the cache, it happens completely automatically. Except for following the proper procedures for shutdown and removing floppies, you do not need to worry about it.
|
今天自己编码试了一下,发现只有在open函数打开文件时,设置了O_SYNC标志,内存才不明显的被消耗.
即使在打开文件后再调用fcntl设置O_SYNC标志也是没有,内存同样的明显的消耗.个人觉得设置O_SYNC标志应该是可以完成同步I/O的,可以是我自已做的时候有某些地方没做到位的原因.
DESCRIPTION
The function fflush() forces a write of all user-space buffered data for the given output or update stream via the
stream's underlying write function. The open status of the stream is unaffected.
fflush只是将用户空间的缓冲区数据写到流里,这并不表示写到磁盘中,可能是弄到kernel block buffered中了.
即使在打开文件后再调用fcntl设置O_SYNC标志也是没有,内存同样的明显的消耗.个人觉得设置O_SYNC标志应该是可以完成同步I/O的,可以是我自已做的时候有某些地方没做到位的原因.
DESCRIPTION
The function fflush() forces a write of all user-space buffered data for the given output or update stream via the
stream's underlying write function. The open status of the stream is unaffected.
fflush只是将用户空间的缓冲区数据写到流里,这并不表示写到磁盘中,可能是弄到kernel block buffered中了.
/*----------------nobuf2.c------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_LEN 1024*1024
int main(int argc,char *argv[])
{
FILE *fp;
int fd;
int loop=20;
char buf[MAX_LEN];
struct sysinfo info;
int flag;
memset(buf,'a',MAX_LEN);
if(argc!=2)
{
printf("Usage:%s filenamen",argv[0]);
exit(0);
}
if((fp=fopen(argv[1],"a+"))==NULL)
{
fprintf(stderr,"can not open file!n");
exit(1);
}
if((fd=fileno(fp)) ./nobuf2 buf.dat
free memory:6196 KB
free memory:5848 KB
free memory:6008 KB
free memory:5904 KB
free memory:5820 KB
free memory:5728 KB
free memory:6352 KB
free memory:6380 KB
free memory:6292 KB
free memory:6132 KB
free memory:6300 KB
free memory:6064 KB
free memory:5980 KB
free memory:5880 KB
free memory:6036 KB
free memory:5828 KB
free memory:6580 KB
free memory:6304 KB
free memory:6096 KB
free memory:7572 KB
after closing. free memory:7572 KB
上面连续执行了几次,只有当free memory达到6000KB左右,内存才基本保持不变.
/*------------------nobuf.c------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_LEN 1024*1024
int main(int argc,char *argv[])
{
FILE *fp;
int fd;
int loop=20;
char buf[MAX_LEN];
struct sysinfo info;
int flag;
memset(buf,'a',MAX_LEN);
if(argc!=2)
{
printf("Usage:%s filenamen",argv[0]);
exit(0);
}
if((fd=open(argv[1],O_WRONLY | O_CREAT | O_SYNC,0666))