It is better to be boldly decisive and risk being wrong than to agnonize at length and be right too late.--------宁可大胆果断,冒险犯错,而不要犹豫不定,正确的太晚
Linux下每种资源都有相关的软硬限制,譬如单个用户多能创建的子进程个数有限制,同样一个进程多能打开的文件描述符 也有相应的限制值,这些限制会限制服务器能够提供并发访问的客户端的数量。
1, 如何修改文件最大句柄数
linux默认最大文件句柄数是1024个,在linux服务器文件并发量比较大的情况下,系统会报"too many open files"的错误。
故在linux服务器高并发调优时,往往需要预先调优Linux参数,修改Linux最大文件句柄数。
方法一
- ulimit -n <可以同时打开的文件数>,将当前进程的最大句柄数修改为指定的参数
注
:该方法只针对当前进程有效,重新打开一个shell或者重新开启一个进程,参数还是之前的值
首先用ulimit -a查询Linux相关的参数,如下所示:
- 其中,open files就是最大文件句柄数,默认是1024个。
- 修改Linux最大文件句柄数: ulimit -n 2048, 将最大句柄数修改为 2048个。
方法二
对所有进程都有效的方法,修改Linux系统参数
vi /etc/security/limits.conf
添加
* soft nofile 65536
* hard nofile 65536
将最大句柄数改为65536修改以后保存,注销当前用户,重新登录,修改后的参数就生效了
2, 修改系统限制API函数
在Linux系统下,我们可以使用下面两个函数
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim); //获取系统限制信息
int setrlimit(int resource, const struct rlimit *rlim); //修改系统限制
设置打开文件描述符数(RLIMIT_NOFILE)、创建进程数(RLIMIT_NPROC)等限制
- 成功返回0,失败返回非0
参数说明:
- 参数 resource说明:
RLIMIT_AS //进程的大虚内存空间,字节为单位。
RLIMIT_CORE //内核转存文件的大长度。
RLIMIT_CPU //大允许的CPU使用时间,秒为单位。当进程达到软限制,内核将给其发送SIGXCPU信号,这一信号的 默认行为是终止进程的执行。
RLIMIT_DATA //进程数据段的大值。
RLIMIT_FSIZE //进程可建立的文件的大长度。如果进程试图超出这一限制时,核心会给其发送SIGXFSZ信号,默认情 况下将终止进程的执行。
RLIMIT_LOCKS //进程可建立的锁和租赁的大值。
RLIMIT_MEMLOCK //进程可锁定在内存中的大数据量,字节为单位。
RLIMIT_MSGQUEUE //进程可为POSIX消息队列分配的大字节数。
RLIMIT_NICE //进程可通过setpriority() 或 nice()调用设置的大完美值。
RLIMIT_NOFILE //指定比进程可打开的大文件描述词大一的值,超出此值,将会产生EMFILE错误。
RLIMIT_NPROC //用户可拥有的大进程数。
RLIMIT_RTPRIO //进程可通过sched_setscheduler 和 sched_setparam设置的大实时优先级。 RLIMIT_SIGPENDING //用户可拥有的大挂起信号数。
RLIMIT_STACK //大的进程堆栈,以字节为单位。
- rlim:描述资源软硬限制的结构体
struct rlimit
{
rlim_t rlim_cur; //指定当前系统软限制
rlim_t rlim_max; //指定的资源指定当前系统的硬限制
};
需要说明:软限制值必须小于硬限制值
下面给出示例代码:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/resource.h>
//下面定义一个函数用来打印系统限制
void print_limits(char* name, int resource)
{
struct rlimit limit;
if(getrlimit(resource, &limit) < 0)
{
printf("getrlimit failure: %s\n", strerror(errno));
return ;
}
printf("%-15s ",name);
//判断软限制是否无限
if(limit.rlim_cur == RLIM_INFINITY)
{
printf(" (infinite) ");
}
else
{
printf(" %-15ld ",limit.rlim_cur);
}
//判断硬限制是否无限
if(limit.rlim_max == RLIM_INFINITY)
{
printf(" (infinite) ");
}else
{
printf(" %-15ld ",limit.rlim_max);
}
printf("\n");
}
//主函数
int main(void)
{
struct rlimit limit = {0};
printf("name softlimit hardlimit\n");
print_limits("RLIMIT_NPROC", RLIMIT_NPROC); //打印进程限制
print_limits("RLIMIT_DATA", RLIMIT_DATA); //打印进程数据段的大值
print_limits("RLIMIT_STACK", RLIMIT_STACK); //打印大的进程堆栈
print_limits("RLIMIT_NOFILE", RLIMIT_NOFILE); //打印文件限制
printf("\nAfter set RLIMIT_NOFILE:\n");
getrlimit(RLIMIT_NOFILE, &limit );
limit.rlim_cur = limit.rlim_max;
setrlimit(RLIMIT_NOFILE, &limit );
print_limits("RLIMIT_NOFILE", RLIMIT_NOFILE);
return 0;
}