« | August 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | | |
| 公告 |
戒除浮躁,读好书,交益友 |
Blog信息 |
blog名称:邢红瑞的blog 日志总数:523 评论数量:1142 留言数量:0 访问次数:9693744 建立时间:2004年12月20日 |

| |
[linux kernel]solaris里面fopen打开文件数的限制  原创空间, 文章收藏, 网上资源, 软件技术, 电脑与网络
邢红瑞 发表于 2008/8/5 10:22:50 |
cyt师傅说的,如果不用读写的话,open快,如果一般文本读写的话,fopen快。但如果自己控制的好,open的读写和fopen一样快。fopen打开的文件超过256后,再使用fopen时就会出错EMFILE,Too many open files,但是使用open调用的时候就不会出现这个错误。用脚本tfc.sh保证所有的文件都存在 #! /bin/sh MAX=260 index=0 FILENAME=test while [ $index -lt $MAX ] do touch $FILENAME$index index=`expr $index + 1` donefopen的例子 如下: #include <stdio.h> #include <syslog.h> #include <errno.h> #define MAX 260 #define FILENAME "test" main() { int i; char filename[256]; FILE *fp; openlog("test1", LOG_PID, LOG_USER); for (i = 0; i < MAX; i++) { snprintf(filename, 256, "%s%d", FILENAME, i); if ((fp = fopen(filename, "r")) == NULL) { syslog(LOG_ERR, "open file %s error, errno %d", filename, errno); } } closelog(); } open的例子#include <stdio.h> #include <syslog.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define MAX 260 #define FILENAME "test" main() { int i; char filename[256]; int fd; openlog("test2", LOG_PID, LOG_USER); for (i = 0; i < MAX; i++) { snprintf(filename, 256, "%s%d", FILENAME, i); if ((fd = open(filename, O_RDONLY, 0)) == -1) { syslog(LOG_ERR, "open file %s error, errno %d", filename, errno); } } closelog(); } 这个程序不会出错,当然前提是ulimit -H -n和ulimit -S -n均大于256。1)修改了/etc/system中的定义,并重新启动了机器。set rlim_fd_max = 4096set rlim_fd_cur = 1024
2)在用户的.cshrc里面设置了 limit descriptors 1024
3)用命令 ulimit -Sn已经能看到改为了1024
但运行程序时,打开文件数目到256以后,再想打开文件,还是出错了.因为256的限制来自于FILE结构的实现。FILE里用unsigned char记录stream对应的描述符,所以只能是0~255。这个限制只在32位系统存在,对于64bit系统,FILE结构被重新定义了,不再有这个限制。open返回的是int,所以没有这个限制。其实fopen在 64位的solaris 2.8上也只能打开255个。改成open函数是可以。但open不能用像fprintf那样的函数进行格式化输出了。
sun专家的建议
Solaris中关于参数rlim_fd_max和rlim_fd_cur的设置讨论
一、概述
很多开发者在编程的时候经常遇到了文件描述符不够用的情况,比如说这样的一个程序,程序首先创建125个的管道(用 pipe(fd[2])来创建),但不释放,接着再打开文件,你就会发现只能打开6个文件,就再也不能打开文件了(fopen()函数返回错误)。按我们的经验觉得在Solaris 8上肯定不止这些文件描述符,但是确实只能使用125*2+6=256个文件描述符(因为一个管道拥有两个描述符)。其实程序能使用的文件描述符受 rlim_fd_max和rlim_fd_cur这两个kernal参数设置的限制,在/etc/system文件里即使把这两个参数值设置成最 65535,仍然只能再打开若干个文件后fopen函数就会返回错误值,但这两个参数的改变确实影响着程序的执行结果。
二、设置修改参数值
其实在系统里面有这样一个命令ulimit,以下是ulimit -a执行的结果:time(seconds) unlimitedfile(blocks) unlimiteddata(kbytes) unlimitedstack(kbytes) 8192coredump(blocks) unlimitednofiles(descriptors) 1024memory(kbytes) unlimited
其中nofiles就是文件描述符的变量值,该值受rlim_fd_cur这个参数的影响,可以用ulimit -n number命令来修改。但不管怎么改,程序仍然不能突破fd=256的限制。在Solaris Tunable Parameters Reference Manua这本书里面能查到以下的资料:A 32-bit program using standard I/O is limited to 256 file descriptors。A 64-bit program using standard I/O can use up to 2 billion descriptors。
这也就是说32位的程序是没有办法突破这个限制的,只有64位的程序才能使用高达2亿个文件描述符,SUN的软硬件在很早以前就实现了64位的架构,现在唯一要解决的就是将程序编译成64位程序,为了生成64位程序,就必须要有64位的编译器(其实不是这样的),如果你去www.sunfreeware.com下载64位编译器gcc,网站上没有特别注明是64位的gcc,但是会有个意外的收获,就是该软件的说明里面注明了只要在用gcc编译的时候加上-m64的option就能生成64位程序了。
于是用gcc -m64去编译生成一个64位程序后,用ulimit -n 102400将number of fd设成很大的情况下,所有问题迎刃而解,再也不存在文件描述符不够用的情况。
在/etc/system文件设置rlimi_fc_max和rlim_fd_cur格式如下:set rlim_fd_max=65535set rlim_fd_cur=102400
命令ulimit使用格式如下:usage: ulimit [ -HSacdfnstv ] [ limit ]ulimit -a是显示各参数的设置值,ulimit -n是用来设置fd的最大值的。
我写的测试代码
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>int main(){ int erron; int size=0; int max=0; FILE *fp[1024]; int i; char filename[256]; max=getdtablesize(); printf("max fd=%d\n ",max); strcpy(filename,"./test.txt"); for(i=0;i<1024;i++){ if ((fp[i]=fopen(filename, "r"))==NULL){ printf("fopen() error %x\n",erron); return -1; } printf("cur fd num:%d\n",i+1); } return 0; }
linux 没有这个限制。 |
|
|