- 浏览: 258797 次
- 性别:
- 来自: 未定
文章分类
最新评论
-
zl544434558:
最后一行</filter> 多余的
Springmvc 乱码问题 -
imknown:
方法有效,感谢博主!
Springmvc 乱码问题 -
notafreak:
方法有效,感谢博主
Springmvc 乱码问题 -
linvar:
ligangdufs 写道 what about resin ...
Springmvc 乱码问题 -
ligangdufs:
what about resin
Springmvc 乱码问题
linux的ulimit各种限制之深入分析
- 博客分类:
- linux
原文链接:http://home.lupaworld.com/home-space-uid-56821-do-blog-id-232810.html
一般可以通过ulimit命令或编辑/etc/security/limits.conf重新加载的方式使之生效
通过ulimit比较直接,但只在当前的session有效,limits.conf中可以根据用户和限制项使用户在下次登录中生效.
对于limits.conf的设定是通过pam_limits.so的加载生效的,比如/etc/pam.d/sshd,这样通过ssh登录时会加载limit.
又或者在/etc/pam.d/login加载生效.
下面将对各种限制进行分析
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20 a
file size (blocks, -f) unlimited a
pending signals (-i) 16382
max locked memory (kbytes, -l) 64 a
max memory size (kbytes, -m) unlimited a
open files (-n) 1024 a
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
一)限制进程产生的文件大小(file size)
先来说说ulimit的硬限制和软限制
硬限制用-H参数,软限制用-S参数.
ulimit -a看到的是软限制,通过ulimit -a -H可以看到硬限制.
如果ulimit不限定使用-H或-S,此时它会同时把两类限制都改掉的.
软限制可以限制用户/组对资源的使用,硬限制的作用是控制软限制.
超级用户和普通用户都可以扩大硬限制,但超级用户可以缩小硬限制,普通用户则不能缩小硬限制.
硬限制设定后,设定软限制时只能是小于或等于硬限制.
下面的测试应用于硬限制和软限制.
1)软限制不能超过硬限制
在超级用户下,同时修改硬/软限制,使当前会话只能建100KB的文件
ulimit -f 100
查看当前创建文件大小的硬限制为100KB
ulimit -H -f
100
此时限制当前会话的软限制为1000KB,出现不能修改的报错
ulimit -S -f 1000
-bash: ulimit: file size: cannot modify limit: Invalid argument
2)硬限制不能小于软限制
在超级用户下,用户查看当前的软限制,此时为unlmiited
ulimit -S -f
unlimited
此时修改当前会话创建文件大小的硬限制为1000KB,出现不能修改的报错,说明硬限制不能小于软限制
ulimit -H -f 1000
-bash: ulimit: file size: cannot modify limit: Invalid argument
如果我们把创建文件大小的软限制改为900KB,此后就可以修改它的硬限制了
ulimit -S -f 900
ulimit -H -f 1000
3)普通用户只能缩小硬限制,超级用户可以扩大硬限制
用普通用户进入系统
su - test
查看创建文件大小的硬限制
ulimit -H -f
unlimited
此时可以缩小该硬限制
ulimit -H -f 1000
但不能扩大该硬限制
ulimit -H -f 10000
4)硬限制控制软限制,软限制来限制用户对资源的使用
用软限制限制创建文件的大小为1000KB
ulimit -S -f 1000
用硬限制限制创建文件的大小为2000KB
ulimit -H -f 2000
创建3MB大小的文件
dd if=/dev/zero of=/tmp/test bs=3M count=1
File size limit exceeded
查看/tmp/test的大小为1000KB,说明软限制对资源的控制是起决定性作用的.
ls -lh /tmp/test
-rw-r--r-- 1 root root 1000K 2010-10-15 23:04 /tmp/test
file size单位是KB.
二)关于进程优先级的限制(scheduling priority)
这里的优先级指NICE值
这个值只对普通用户起作用,对超级用户不起作用,这个问题是由于CAP_SYS_NICE造成的.
例如调整普通用户可以使用的nice值为-10到20之间.
硬限制nice的限制为-15到20之间.
ulimit -H -e 35
软限制nice的限制为-10到20之间
ulimit -S -e 30
用nice命令,使执行ls的nice值为-10
nice -n -10 ls /tmp
ssh-BossiP2810 ssh-KITFTp2620 ssh-vIQDXV3333
用nice命令,使执行ls的nice值为-11,此时超过了ulimit对nice的软限制,出现了异常.
nice -n -11 ls /tmp
nice: cannot set niceness: Permission denied
三)内存锁定值的限制(max locked memory)
这个值只对普通用户起作用,对超级用户不起作用,这个问题是由于CAP_IPC_LOCK造成的.
linux对内存是分页管理的,这意味着有不需要时,在物理内存的数据会被换到交换区或磁盘上.
有需要时会被交换到物理内存,而将数据锁定到物理内存可以避免数据的换入/换出.
采用锁定内存有两个理由:
1)由于程序设计上需要,比如oracle等软件,就需要将数据锁定到物理内存.
2)主要是安全上的需要,比如用户名和密码等等,被交换到swap或磁盘,有泄密的可能,所以一直将其锁定到物理内存.
锁定内存的动作由mlock()函数来完成
mlock的原型如下:
int mlock(const void *addr,size_t len);
测试程序如下:
#include <stdio.h>
#include <sys/mman.h>
int main(int argc, char* argv[])
{
int array[2048];
if (mlock((const void *)array, sizeof(array)) == -1) {
perror("mlock: ");
return -1;
}
printf("success to lock stack mem at: %p, len=%zd\n",
array, sizeof(array));
if (munlock((const void *)array, sizeof(array)) == -1) {
perror("munlock: ");
return -1;
}
printf("success to unlock stack mem at: %p, len=%zd\n",
array, sizeof(array));
return 0;
}
gcc mlock_test.c -o mlock_test
上面这个程序,锁定2KB的数据到物理内存中,我们调整ulimit的max locked memory.
ulimit -H -l 4
ulimit -S -l 1
./mlock_test
mlock: : Cannot allocate memory
我们放大max locked memory的限制到4KB,可以执行上面的程序了.
ulimit -S -l 4
./mlock_test
success to lock stack mem at: 0x7fff1f039500, len=2048
success to unlock stack mem at: 0x7fff1f039500, len=2048
注意:如果调整到3KB也不能执行上面的程序,原因是除了这段代码外,我们还会用其它动态链接库.
四)进程打开文件的限制(open files)
这个值针对所有用户,表示可以在进程中打开的文件数.
例如我们将open files的值改为3
ulimit -n 3
此时打开/etc/passwd文件时失败了.
cat /etc/passwd
-bash: start_pipeline: pgrp pipe: Too many open files
-bash: /bin/cat: Too many open files
五)信号可以被挂起的最大数(pending signals)
这个值针对所有用户,表示可以被挂起/阻塞的最大信号数量
我们用以下的程序进行测试,源程序如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
volatile int done = 0;
void handler (int sig)
{
const char *str = "handled...\n";
write (1, str, strlen(str));
done = 1;
}
void child(void)
{
int i;
for (i = 0; i < 3; i++){
kill(getppid(), SIGRTMIN);
printf("child - BANG!\n");
}
exit (0);
}
int main (int argc, char *argv[])
{
signal (SIGRTMIN, handler);
sigset_t newset, oldset;
sigfillset(&newset);
sigprocmask(SIG_BLOCK, &newset, &oldset);
pid_t pid = fork();
if (pid == 0)
child();
printf("parent sleeping \n");
int r = sleep(3);
printf("woke up! r=%d\n", r);
sigprocmask(SIG_SETMASK, &oldset, NULL);
while (!done){
};
printf("exiting\n");
exit(0);
}
编译源程序:
gcc test.c -o test
执行程序test,这时子程序发送了三次SIGRTMIN信号,父程序在过3秒后,接收并处理该信号.
./test
parent sleeping
child - BANG!
child - BANG!
child - BANG!
woke up! r=0
handled...
handled...
handled...
exiting
注意:这里有采用的是发送实时信号(SIGRTMIN),如:kill(getppid(), SIGRTMIN);
如果不是实时信号,则只能接收一次.
如果我们将pending signals值改为2,这里将只能保证挂起两个信号,第三个信号将被忽略.如下:
ulimit -i 2
./test
parent sleeping
child - BANG!
child - BANG!
child - BANG!
woke up! r=0
handled...
handled...
exiting
六)可以创建使用POSIX消息队列的最大值,单位为bytes.(POSIX message queues)
我们用下面的程序对POSIX消息队列的限制进行测试,如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <sys/stat.h>
#include <sys/wait.h>
struct message{
char mtext[128];
};
int send_msg(int qid, int pri, const char text[])
{
int r = mq_send(qid, text, strlen(text) + 1,pri);
if (r == -1){
perror("mq_send");
}
return r;
}
void producer(mqd_t qid)
{
send_msg(qid, 1, "This is my first message.");
send_msg(qid, 1, "This is my second message.");
send_msg(qid, 3, "No more messages.");
}
void consumer(mqd_t qid)
{
struct mq_attr mattr;
do{
u_int pri;
struct message msg;
ssize_t len;
len = mq_receive(qid, (char *)&msg, sizeof(msg), &pri);
if (len == -1){
perror("mq_receive");
break;
}
printf("got pri %d '%s' len=%d\n", pri, msg.mtext, len);
int r = mq_getattr(qid, &mattr);
if (r == -1){
perror("mq_getattr");
break;
}
}while(mattr.mq_curmsgs);
}
int
main (int argc, char *argv[])
{
struct mq_attr mattr = {
.mq_maxmsg = 10,
.mq_msgsize = sizeof(struct message)
};
mqd_t mqid = mq_open("/myq",
O_CREAT|O_RDWR,
S_IREAD|S_IWRITE,
&mattr);
if (mqid == (mqd_t) -1){
perror("mq_open");
exit (1);
}
pid_t pid = fork();
if (pid == 0){
producer(mqid);
mq_close(mqid);
exit(0);
}
else
{
int status;
wait(&status);
consumer(mqid);
mq_close(mqid);
}
mq_unlink("/myq");
return 0;
}
编译:
gcc test.c -o test
限制POSIX消息队列的最大值为1000个字节
ulimit -q 1000
这里我们执行test程序
./test
mq_open: Cannot allocate memory
程序报告无法分配内存.
用strace来跟踪test的运行过程,在下面一条语句时报错.
mq_open("myq", O_RDWR|O_CREAT, 0600, {mq_maxmsg=10, mq_msgsize=128}) = -1 ENOMEM (Cannot allocate memory)
{mq_maxmsg=10, mq_msgsize=128}即128*10=1280个字节,说明已经超过了1000个字节的POSIX消息队列限制.
我们将POSIX消息队列的最大值调整为1360时,程序可以运行.
ulimit -q 1360
./test
got pri 3 'No more messages.' len=18
got pri 1 'This is my first message.' len=26
got pri 1 'This is my second message.' len=27
七)程序占用CPU的时间,单位是秒(cpu time)
我们用下面的代码对程序占用CPU时间的限制进行测试
源程序如下:
# include <stdio.h>
# include <math.h>
int main (void)
{
double pi=M_PI;
double pisqrt;
long i;
while(1){
pisqrt=sqrt(pi);
}
return 0;
}
编译:
gcc test.c -o test -lm
运行程序test,程序会一直循环下去,只有通过CTRL+C中断.
./test
^C
用ulimit将程序占用CPU的时间改为2秒,再运行程序.
ulimit -t 2
./test
Killed
程序最后被kill掉了.
八)限制程序实时优先级的范围,只针对普通用户.(real-time priority)
我们用下面的代码对程序实时优先级的范围进行测试
源程序如下:
# include <stdio.h>
int main (void)
{
int i;
for (i=0;i<6;i++)
{
printf ("%d\n",i);
sleep(1);
}
return 0;
}
编译:
gcc test.c -o test
切换到普通用户进行测试
su - ckhitler
用实时优先级20运行test程序
chrt -f 20 ./test
chrt: failed to set pid 0's policy: Operation not permitted
我们用root将ulimit的实时优先级调整为20.再进行测试.
su - root
ulimit -r 20
切换到普通用户,用实时优先级20运行程序,可以运行这个程序了.
su - ckhitler
chrt -r 20 ./test
0
1
2
3
4
5
以实时优先级50运行程序,还是报错,说明ulimit的限制起了作用.
chrt -r 50 ./test
chrt: failed to set pid 0's policy: Operation not permitted
九)限制程序可以fork的进程数,只对普通用户有效(max user processes)
我们用下面的代码对程序的fork进程数的范围进行测试
源程序如下:
#include <unistd.h>
#include <stdio.h>
int main(void)
{
pid_t pid;
int count=0;
while (count<3){
pid=fork();
count++;
printf("count= %d\n",count);
}
return 0;
}
编译:
gcc test.c -o test
count= 1
count= 2
count= 3
count= 2
count= 3
count= 1
count= 3
count= 2
count= 3
count= 3
count= 3
count= 2
count= 3
count= 3
程序fork的进程数成倍的增加,这里是14个进程的输出.除自身外,其它13个进程都是test程序fork出来的.
我们将fork的限定到12,如下:
ulimit -u 12
再次执行test程序,这里只有12个进程的输出.
./test
count= 1
count= 2
count= 3
count= 1
count= 2
count= 3
count= 2
count= 3
count= 3
count= 2
count= 3
count= 3
count= 3
十)限制core文件的大小(core file size)
我们用下面的代码对程序生成core的大小进行测试
源代码:
#include <stdio.h>
static void sub(void);
int main(void)
{
sub();
return 0;
}
static void sub(void)
{
int *p = NULL;
printf("%d", *p);
}
编译:
gcc -g test.c -o test
运行程序test,出现段错误.
./test
Segmentation fault (core dumped)
如果在当前目录下没有core文件,我们应该调整ulimit对core的大小进行限制,如果core文件大小在这里指定为0,将不会产生core文件.
这里设定core文件大小为10个blocks.注:一个blocks在这里为1024个字节.
ulimit -c 10
再次运行这个程序
./test
Segmentation fault (core dumped)
查看core文件的大小
ls -lh core
-rw------- 1 root root 12K 2011-03-08 13:54 core
我们设定10个blocks应该是10*1024也不是10KB,为什么它是12KB呢,因为它的递增是4KB.
如果调整到14个blocks,我们将最大产生16KB的core文件.
十一)限制进程使用数据段的大小(data seg size)
一般来说这个限制会影响程序调用brk(系统调用)和sbrk(库函数)
调用malloc时,如果发现vm不够了就会用brk去内核申请.
限制可以使用最大为1KB的数据段
ulimit -d 1
用norff打开/etc/passwd文件
nroff /etc/passwd
Segmentation fault
可以用strace来跟踪程序的运行.
strace nroff /etc/passwd
打印出如下的结果,证明程序在分配内存时不够用时,调用brk申请新的内存,而由于ulimit的限制,导致申请失败.
munmap(0x7fc2abf00000, 104420) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], = 0
open("/dev/tty", O_RDWR|O_NONBLOCK) = 3
close(3) = 0
brk(0) = 0xf5b000
brk(0xf5c000) = 0xf5b000
brk(0xf5c000) = 0xf5b000
brk(0xf5c000) = 0xf5b000
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault
我们这里用一个测试程序对data segment的限制进行测试.
源程序如下:
#include <stdio.h>
int main()
{
int start,end;
start = sbrk(0);
(char *)malloc(32*1024);
end = sbrk(0);
printf("hello I used %d vmemory\n",end - start);
return 0;
}
gcc test.c -o test
./test
hello I used 0 vmemory
通过ulimit将限制改为170KB
再次运行程序
./test
hello I used 167936 vmemory
十二)限制进程使用堆栈段的大小
我们用ulimit将堆栈段的大小调整为16,即16*1024.
ulimit -s 16
再运行命令:
ls -l /etc/
Segmentation fault (core dumped)
这时用strace跟踪命令的运行过程
strace ls -l /etc/
发现它调用getrlimit,这里的限制是16*1024,不够程序运行时用到的堆栈.
getrlimit(RLIMIT_STACK, {rlim_cur=16*1024, rlim_max=16*1024}) = 0
注:在2.6.32系统上ls -l /etc/并不会出现堆栈不够用的情况,这时可以用expect来触发这个问题.
如:
expect
Tcl_Init failed: out of stack space (infinite loop?)
十三)限制进程使用虚拟内存的大小
我们用ulimit将虚拟内存调整为8192KB
ulimit -v 8192
运行ls
ls
ls: error while loading shared libraries: libc.so.6: failed to map segment from shared object: Cannot allocate memory
ls在加载libc.so.6动态库的时候报了错,提示内存不足.
用strace跟踪ls的运行过程,看到下面的输出,说明在做mmap映射出内存时,出现内存不够用.
mmap(NULL, 3680296, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = -1 ENOMEM (Cannot allocate memory)
close(3) = 0
writev(2, [{"ls", 2}, {": ", 2}, {"error while loading shared libra"..., 36}, {": ", 2}, {"libc.so.6", 9}, {": ", 2}, {"failed to map segment from share"..., 40}, {": ", 2}, {"Cannot allocate memory", 22}, {"\n", 1}], 10ls: error while loading shared libraries: libc.so.6: failed to map segment from shared object: Cannot allocate memory
十四)剩下的三种ulimit限制说明(file locks/max memory size/pipe size)
文件锁的限制只在2.4内核之前有用.
驻留内存的限制在很多系统里也没有作用.
管道的缓存不能改变,只能是8*512(bytes),也就是4096个字节.
一般可以通过ulimit命令或编辑/etc/security/limits.conf重新加载的方式使之生效
通过ulimit比较直接,但只在当前的session有效,limits.conf中可以根据用户和限制项使用户在下次登录中生效.
对于limits.conf的设定是通过pam_limits.so的加载生效的,比如/etc/pam.d/sshd,这样通过ssh登录时会加载limit.
又或者在/etc/pam.d/login加载生效.
下面将对各种限制进行分析
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20 a
file size (blocks, -f) unlimited a
pending signals (-i) 16382
max locked memory (kbytes, -l) 64 a
max memory size (kbytes, -m) unlimited a
open files (-n) 1024 a
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
一)限制进程产生的文件大小(file size)
先来说说ulimit的硬限制和软限制
硬限制用-H参数,软限制用-S参数.
ulimit -a看到的是软限制,通过ulimit -a -H可以看到硬限制.
如果ulimit不限定使用-H或-S,此时它会同时把两类限制都改掉的.
软限制可以限制用户/组对资源的使用,硬限制的作用是控制软限制.
超级用户和普通用户都可以扩大硬限制,但超级用户可以缩小硬限制,普通用户则不能缩小硬限制.
硬限制设定后,设定软限制时只能是小于或等于硬限制.
下面的测试应用于硬限制和软限制.
1)软限制不能超过硬限制
在超级用户下,同时修改硬/软限制,使当前会话只能建100KB的文件
ulimit -f 100
查看当前创建文件大小的硬限制为100KB
ulimit -H -f
100
此时限制当前会话的软限制为1000KB,出现不能修改的报错
ulimit -S -f 1000
-bash: ulimit: file size: cannot modify limit: Invalid argument
2)硬限制不能小于软限制
在超级用户下,用户查看当前的软限制,此时为unlmiited
ulimit -S -f
unlimited
此时修改当前会话创建文件大小的硬限制为1000KB,出现不能修改的报错,说明硬限制不能小于软限制
ulimit -H -f 1000
-bash: ulimit: file size: cannot modify limit: Invalid argument
如果我们把创建文件大小的软限制改为900KB,此后就可以修改它的硬限制了
ulimit -S -f 900
ulimit -H -f 1000
3)普通用户只能缩小硬限制,超级用户可以扩大硬限制
用普通用户进入系统
su - test
查看创建文件大小的硬限制
ulimit -H -f
unlimited
此时可以缩小该硬限制
ulimit -H -f 1000
但不能扩大该硬限制
ulimit -H -f 10000
4)硬限制控制软限制,软限制来限制用户对资源的使用
用软限制限制创建文件的大小为1000KB
ulimit -S -f 1000
用硬限制限制创建文件的大小为2000KB
ulimit -H -f 2000
创建3MB大小的文件
dd if=/dev/zero of=/tmp/test bs=3M count=1
File size limit exceeded
查看/tmp/test的大小为1000KB,说明软限制对资源的控制是起决定性作用的.
ls -lh /tmp/test
-rw-r--r-- 1 root root 1000K 2010-10-15 23:04 /tmp/test
file size单位是KB.
二)关于进程优先级的限制(scheduling priority)
这里的优先级指NICE值
这个值只对普通用户起作用,对超级用户不起作用,这个问题是由于CAP_SYS_NICE造成的.
例如调整普通用户可以使用的nice值为-10到20之间.
硬限制nice的限制为-15到20之间.
ulimit -H -e 35
软限制nice的限制为-10到20之间
ulimit -S -e 30
用nice命令,使执行ls的nice值为-10
nice -n -10 ls /tmp
ssh-BossiP2810 ssh-KITFTp2620 ssh-vIQDXV3333
用nice命令,使执行ls的nice值为-11,此时超过了ulimit对nice的软限制,出现了异常.
nice -n -11 ls /tmp
nice: cannot set niceness: Permission denied
三)内存锁定值的限制(max locked memory)
这个值只对普通用户起作用,对超级用户不起作用,这个问题是由于CAP_IPC_LOCK造成的.
linux对内存是分页管理的,这意味着有不需要时,在物理内存的数据会被换到交换区或磁盘上.
有需要时会被交换到物理内存,而将数据锁定到物理内存可以避免数据的换入/换出.
采用锁定内存有两个理由:
1)由于程序设计上需要,比如oracle等软件,就需要将数据锁定到物理内存.
2)主要是安全上的需要,比如用户名和密码等等,被交换到swap或磁盘,有泄密的可能,所以一直将其锁定到物理内存.
锁定内存的动作由mlock()函数来完成
mlock的原型如下:
int mlock(const void *addr,size_t len);
测试程序如下:
#include <stdio.h>
#include <sys/mman.h>
int main(int argc, char* argv[])
{
int array[2048];
if (mlock((const void *)array, sizeof(array)) == -1) {
perror("mlock: ");
return -1;
}
printf("success to lock stack mem at: %p, len=%zd\n",
array, sizeof(array));
if (munlock((const void *)array, sizeof(array)) == -1) {
perror("munlock: ");
return -1;
}
printf("success to unlock stack mem at: %p, len=%zd\n",
array, sizeof(array));
return 0;
}
gcc mlock_test.c -o mlock_test
上面这个程序,锁定2KB的数据到物理内存中,我们调整ulimit的max locked memory.
ulimit -H -l 4
ulimit -S -l 1
./mlock_test
mlock: : Cannot allocate memory
我们放大max locked memory的限制到4KB,可以执行上面的程序了.
ulimit -S -l 4
./mlock_test
success to lock stack mem at: 0x7fff1f039500, len=2048
success to unlock stack mem at: 0x7fff1f039500, len=2048
注意:如果调整到3KB也不能执行上面的程序,原因是除了这段代码外,我们还会用其它动态链接库.
四)进程打开文件的限制(open files)
这个值针对所有用户,表示可以在进程中打开的文件数.
例如我们将open files的值改为3
ulimit -n 3
此时打开/etc/passwd文件时失败了.
cat /etc/passwd
-bash: start_pipeline: pgrp pipe: Too many open files
-bash: /bin/cat: Too many open files
五)信号可以被挂起的最大数(pending signals)
这个值针对所有用户,表示可以被挂起/阻塞的最大信号数量
我们用以下的程序进行测试,源程序如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
volatile int done = 0;
void handler (int sig)
{
const char *str = "handled...\n";
write (1, str, strlen(str));
done = 1;
}
void child(void)
{
int i;
for (i = 0; i < 3; i++){
kill(getppid(), SIGRTMIN);
printf("child - BANG!\n");
}
exit (0);
}
int main (int argc, char *argv[])
{
signal (SIGRTMIN, handler);
sigset_t newset, oldset;
sigfillset(&newset);
sigprocmask(SIG_BLOCK, &newset, &oldset);
pid_t pid = fork();
if (pid == 0)
child();
printf("parent sleeping \n");
int r = sleep(3);
printf("woke up! r=%d\n", r);
sigprocmask(SIG_SETMASK, &oldset, NULL);
while (!done){
};
printf("exiting\n");
exit(0);
}
编译源程序:
gcc test.c -o test
执行程序test,这时子程序发送了三次SIGRTMIN信号,父程序在过3秒后,接收并处理该信号.
./test
parent sleeping
child - BANG!
child - BANG!
child - BANG!
woke up! r=0
handled...
handled...
handled...
exiting
注意:这里有采用的是发送实时信号(SIGRTMIN),如:kill(getppid(), SIGRTMIN);
如果不是实时信号,则只能接收一次.
如果我们将pending signals值改为2,这里将只能保证挂起两个信号,第三个信号将被忽略.如下:
ulimit -i 2
./test
parent sleeping
child - BANG!
child - BANG!
child - BANG!
woke up! r=0
handled...
handled...
exiting
六)可以创建使用POSIX消息队列的最大值,单位为bytes.(POSIX message queues)
我们用下面的程序对POSIX消息队列的限制进行测试,如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <mqueue.h>
#include <sys/stat.h>
#include <sys/wait.h>
struct message{
char mtext[128];
};
int send_msg(int qid, int pri, const char text[])
{
int r = mq_send(qid, text, strlen(text) + 1,pri);
if (r == -1){
perror("mq_send");
}
return r;
}
void producer(mqd_t qid)
{
send_msg(qid, 1, "This is my first message.");
send_msg(qid, 1, "This is my second message.");
send_msg(qid, 3, "No more messages.");
}
void consumer(mqd_t qid)
{
struct mq_attr mattr;
do{
u_int pri;
struct message msg;
ssize_t len;
len = mq_receive(qid, (char *)&msg, sizeof(msg), &pri);
if (len == -1){
perror("mq_receive");
break;
}
printf("got pri %d '%s' len=%d\n", pri, msg.mtext, len);
int r = mq_getattr(qid, &mattr);
if (r == -1){
perror("mq_getattr");
break;
}
}while(mattr.mq_curmsgs);
}
int
main (int argc, char *argv[])
{
struct mq_attr mattr = {
.mq_maxmsg = 10,
.mq_msgsize = sizeof(struct message)
};
mqd_t mqid = mq_open("/myq",
O_CREAT|O_RDWR,
S_IREAD|S_IWRITE,
&mattr);
if (mqid == (mqd_t) -1){
perror("mq_open");
exit (1);
}
pid_t pid = fork();
if (pid == 0){
producer(mqid);
mq_close(mqid);
exit(0);
}
else
{
int status;
wait(&status);
consumer(mqid);
mq_close(mqid);
}
mq_unlink("/myq");
return 0;
}
编译:
gcc test.c -o test
限制POSIX消息队列的最大值为1000个字节
ulimit -q 1000
这里我们执行test程序
./test
mq_open: Cannot allocate memory
程序报告无法分配内存.
用strace来跟踪test的运行过程,在下面一条语句时报错.
mq_open("myq", O_RDWR|O_CREAT, 0600, {mq_maxmsg=10, mq_msgsize=128}) = -1 ENOMEM (Cannot allocate memory)
{mq_maxmsg=10, mq_msgsize=128}即128*10=1280个字节,说明已经超过了1000个字节的POSIX消息队列限制.
我们将POSIX消息队列的最大值调整为1360时,程序可以运行.
ulimit -q 1360
./test
got pri 3 'No more messages.' len=18
got pri 1 'This is my first message.' len=26
got pri 1 'This is my second message.' len=27
七)程序占用CPU的时间,单位是秒(cpu time)
我们用下面的代码对程序占用CPU时间的限制进行测试
源程序如下:
# include <stdio.h>
# include <math.h>
int main (void)
{
double pi=M_PI;
double pisqrt;
long i;
while(1){
pisqrt=sqrt(pi);
}
return 0;
}
编译:
gcc test.c -o test -lm
运行程序test,程序会一直循环下去,只有通过CTRL+C中断.
./test
^C
用ulimit将程序占用CPU的时间改为2秒,再运行程序.
ulimit -t 2
./test
Killed
程序最后被kill掉了.
八)限制程序实时优先级的范围,只针对普通用户.(real-time priority)
我们用下面的代码对程序实时优先级的范围进行测试
源程序如下:
# include <stdio.h>
int main (void)
{
int i;
for (i=0;i<6;i++)
{
printf ("%d\n",i);
sleep(1);
}
return 0;
}
编译:
gcc test.c -o test
切换到普通用户进行测试
su - ckhitler
用实时优先级20运行test程序
chrt -f 20 ./test
chrt: failed to set pid 0's policy: Operation not permitted
我们用root将ulimit的实时优先级调整为20.再进行测试.
su - root
ulimit -r 20
切换到普通用户,用实时优先级20运行程序,可以运行这个程序了.
su - ckhitler
chrt -r 20 ./test
0
1
2
3
4
5
以实时优先级50运行程序,还是报错,说明ulimit的限制起了作用.
chrt -r 50 ./test
chrt: failed to set pid 0's policy: Operation not permitted
九)限制程序可以fork的进程数,只对普通用户有效(max user processes)
我们用下面的代码对程序的fork进程数的范围进行测试
源程序如下:
#include <unistd.h>
#include <stdio.h>
int main(void)
{
pid_t pid;
int count=0;
while (count<3){
pid=fork();
count++;
printf("count= %d\n",count);
}
return 0;
}
编译:
gcc test.c -o test
count= 1
count= 2
count= 3
count= 2
count= 3
count= 1
count= 3
count= 2
count= 3
count= 3
count= 3
count= 2
count= 3
count= 3
程序fork的进程数成倍的增加,这里是14个进程的输出.除自身外,其它13个进程都是test程序fork出来的.
我们将fork的限定到12,如下:
ulimit -u 12
再次执行test程序,这里只有12个进程的输出.
./test
count= 1
count= 2
count= 3
count= 1
count= 2
count= 3
count= 2
count= 3
count= 3
count= 2
count= 3
count= 3
count= 3
十)限制core文件的大小(core file size)
我们用下面的代码对程序生成core的大小进行测试
源代码:
#include <stdio.h>
static void sub(void);
int main(void)
{
sub();
return 0;
}
static void sub(void)
{
int *p = NULL;
printf("%d", *p);
}
编译:
gcc -g test.c -o test
运行程序test,出现段错误.
./test
Segmentation fault (core dumped)
如果在当前目录下没有core文件,我们应该调整ulimit对core的大小进行限制,如果core文件大小在这里指定为0,将不会产生core文件.
这里设定core文件大小为10个blocks.注:一个blocks在这里为1024个字节.
ulimit -c 10
再次运行这个程序
./test
Segmentation fault (core dumped)
查看core文件的大小
ls -lh core
-rw------- 1 root root 12K 2011-03-08 13:54 core
我们设定10个blocks应该是10*1024也不是10KB,为什么它是12KB呢,因为它的递增是4KB.
如果调整到14个blocks,我们将最大产生16KB的core文件.
十一)限制进程使用数据段的大小(data seg size)
一般来说这个限制会影响程序调用brk(系统调用)和sbrk(库函数)
调用malloc时,如果发现vm不够了就会用brk去内核申请.
限制可以使用最大为1KB的数据段
ulimit -d 1
用norff打开/etc/passwd文件
nroff /etc/passwd
Segmentation fault
可以用strace来跟踪程序的运行.
strace nroff /etc/passwd
打印出如下的结果,证明程序在分配内存时不够用时,调用brk申请新的内存,而由于ulimit的限制,导致申请失败.
munmap(0x7fc2abf00000, 104420) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], = 0
open("/dev/tty", O_RDWR|O_NONBLOCK) = 3
close(3) = 0
brk(0) = 0xf5b000
brk(0xf5c000) = 0xf5b000
brk(0xf5c000) = 0xf5b000
brk(0xf5c000) = 0xf5b000
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault
我们这里用一个测试程序对data segment的限制进行测试.
源程序如下:
#include <stdio.h>
int main()
{
int start,end;
start = sbrk(0);
(char *)malloc(32*1024);
end = sbrk(0);
printf("hello I used %d vmemory\n",end - start);
return 0;
}
gcc test.c -o test
./test
hello I used 0 vmemory
通过ulimit将限制改为170KB
再次运行程序
./test
hello I used 167936 vmemory
十二)限制进程使用堆栈段的大小
我们用ulimit将堆栈段的大小调整为16,即16*1024.
ulimit -s 16
再运行命令:
ls -l /etc/
Segmentation fault (core dumped)
这时用strace跟踪命令的运行过程
strace ls -l /etc/
发现它调用getrlimit,这里的限制是16*1024,不够程序运行时用到的堆栈.
getrlimit(RLIMIT_STACK, {rlim_cur=16*1024, rlim_max=16*1024}) = 0
注:在2.6.32系统上ls -l /etc/并不会出现堆栈不够用的情况,这时可以用expect来触发这个问题.
如:
expect
Tcl_Init failed: out of stack space (infinite loop?)
十三)限制进程使用虚拟内存的大小
我们用ulimit将虚拟内存调整为8192KB
ulimit -v 8192
运行ls
ls
ls: error while loading shared libraries: libc.so.6: failed to map segment from shared object: Cannot allocate memory
ls在加载libc.so.6动态库的时候报了错,提示内存不足.
用strace跟踪ls的运行过程,看到下面的输出,说明在做mmap映射出内存时,出现内存不够用.
mmap(NULL, 3680296, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = -1 ENOMEM (Cannot allocate memory)
close(3) = 0
writev(2, [{"ls", 2}, {": ", 2}, {"error while loading shared libra"..., 36}, {": ", 2}, {"libc.so.6", 9}, {": ", 2}, {"failed to map segment from share"..., 40}, {": ", 2}, {"Cannot allocate memory", 22}, {"\n", 1}], 10ls: error while loading shared libraries: libc.so.6: failed to map segment from shared object: Cannot allocate memory
十四)剩下的三种ulimit限制说明(file locks/max memory size/pipe size)
文件锁的限制只在2.4内核之前有用.
驻留内存的限制在很多系统里也没有作用.
管道的缓存不能改变,只能是8*512(bytes),也就是4096个字节.
发表评论
-
Centos6 Installation
2013-10-26 18:22 10871. the FileManager(Nautilus) sh ... -
Linux 系统优化
2011-11-11 00:01 01. 2. 3. 4. -
HP proLiant DL360 G4
2011-10-30 16:49 2172等了大概一个星期, 托管的HP服务器下架托运回来了. 第一次 ... -
linux cmd sample
2011-07-08 13:03 11841.find and sed and xargs find . ... -
linux tip
2011-05-21 08:46 01.top 子命令: "l" load ... -
Locale 详解
2010-12-18 18:13 930from : http://www.linuxsky.org/ ... -
login shell and no login shell
2010-04-01 15:40 1584一般标准的login shell(不单止bash)启动时都会去 ... -
linux 笔记3
2010-03-30 21:17 1006进程控制 1.进程的组成部分 一个进程由一个地址空间和内核内部 ... -
linux日常命令备忘1
2010-03-28 21:22 1125经常有些日常需要用到的命令,虽然一般的选项都OK,但需要深入一 ... -
linux 笔记2
2010-03-28 14:17 1018超级用户 root账号的UID为0,拥有至高的权限 如果使用D ... -
linux 笔记1
2010-03-26 20:23 1244引导和关机 1.引导(bootstrapping)PC (1) ... -
各种linux发行版的配置文件
2010-03-17 15:31 1678linux有许多发行版,各种 ... -
ubuntu9.10源GPG error
2010-02-02 22:37 1411配置ubuntu 163的源后,正常运行了一段时间,速度还行。 ... -
lfs
2010-02-01 14:28 9691.When the kernel boots the sy ... -
linux set,env, export
2010-02-01 08:30 2827set 显示当前shell的变量,包括当前用户的变量 env ... -
linux exec
2010-02-01 07:01 5933shell的内建命令exec将并不启动新的shell,而是用要 ... -
Ubuntu编译环境
2009-03-11 15:00 1713一. 安裝基本的編譯環境和一些輔助工具,如文檔等。 sudo ...
相关推荐
管理员和开发者通过配置和使用ulimit、core_pattern等系统设置,以及采用gdb等调试工具,能够对程序的异常终止进行深入的分析,帮助发现和解决问题。同时,对于系统安全性较高的环境,合理配置Core Dump文件的生成和...
在《Linux性能优化实战》案例中,我们深入探讨了如何利用Linux系统工具和技术来提升系统的运行效率和性能。Linux作为一款开源操作系统,其强大的可定制性和丰富的工具集使其成为性能优化的理想平台。以下是一些核心...
本文将深入探讨如何利用core dump进行Linux应用程序的调试,特别关注使用gdb工具来解析core文件。 ### coredump的核心概念 #### 1. 何时产生core dump? 当进程接收到某些信号(如SIGSEGV)时,如果内核被配置为...
通过对这些环节进行深入分析,我们可以找出系统性能瓶颈,并据此提出性能优化方案。 性能分析的目的在于找出系统中的瓶颈,无论是硬件还是软件,然后通过升级硬件、改进系统结构等方式来优化性能,以达到合理配置,...
3. **进程管理**:包括进程优先级设置(nice和renice命令)、进程限制(ulimit)以及进程调度策略(CFS调度器),以确保关键服务的高效运行。 4. **内存管理**:探讨了Linux的交换机制、内存分配策略(如 slab 和 ...
在深入探讨这些知识点之前,我们首先需要理解Linux系统的基础和它的重要性。Linux是一种自由、开源的操作系统,被广泛应用于服务器、云计算、物联网等领域,其稳定性和安全性备受业界推崇。 **Linux安装后基本优化*...
本主题“Linux安全和优化”将深入探讨如何确保Linux系统的安全性并对其进行性能优化,以实现更高效、安全的运行环境。 一、Linux安全 1. **权限管理**:Linux系统的文件和目录权限是其安全基础,通过chmod和chown...
- ulimit管理系统资源:利用ulimit命令限制进程可使用的资源,防止系统资源被过度占用。 2. 系统服务应用 - Linux上传下载小工具:介绍在Linux环境下,如何使用命令行工具进行文件的上传和下载。 - Rsync+...
同时,结合`free`、`pmap`和`strace`对特定进程或服务进行深入分析,确保系统稳定高效运行。 综上所述,Linux系统性能测试涉及多个层面,从基本的文件系统监控到复杂的多处理器系统分析,都需要相应的工具和技术...
- **栈**:用于存储函数调用的局部变量以及函数参数等临时数据,通常为8MB大小,可通过命令`ulimit -s`查询当前限制。 - **内核虚拟空间**:这部分空间由内核管理,用户程序不可见。 #### 64位系统的虚拟地址空间...
此外,了解资源限制如ulimit,以及内存和CPU使用监控,对于优化程序性能至关重要。 最后,了解版本控制系统如Git,它在协作开发和版本管理中扮演着重要角色。学会使用makefile自动化构建流程,可以提高开发效率。 ...
- **资源限制**:理解如何通过`ulimit`调整用户和进程的资源限制,以优化系统性能和稳定性。 **4. 常见问题解决** - **日志分析**:熟悉查看和解析系统日志文件,例如`/var/log`目录下的各种日志文件。 - **故障...
core文件是Linux下非常有用的调试工具之一,通过合理地设置core文件的生成与命名规则,并结合使用GDB和其他辅助工具,我们可以有效地定位程序中的错误,解决复杂的问题。此外,掌握core文件的高级调试技巧,如多线程...
在本文中,我们将深入探讨Linux下如何处理和分析段错误,特别是如何生成和利用core文件来调试程序。 首先,当一个Linux程序遇到段错误时,如果系统开启了core dump功能,它会将进程的内存映像保存到一个名为`core`...
Linux系统提供了一些高级功能,例如ulimit命令用于管理系统资源,如最大文件大小、进程数等限制。Linux上传下载小工具如lrzsz,可以简化文件的传输。rsync是一个常用的文件同步工具,它可以通过与inotify结合实现...
10. **资源限制**:了解`cgroups`(控制组)如何限制和隔离资源使用,以及`nice`和`ulimit`命令如何调整进程优先级和资源限制。 11. **日志分析**:理解日志文件的重要性,学习如何通过`logrotate`管理日志,以及...
本文将深入讲解Linux core文件的相关知识点。 1. **核心文件的生成** 当程序由于错误、异常或者信号等原因崩溃时,系统可以选择生成一个core文件。默认情况下,这个文件被命名为`core`,并保存在程序执行的当前...
总结来说,Linux性能分析与调整是一个综合性的任务,需要熟练运用各种命令工具,通过观察和分析找出性能瓶颈,并通过内核参数调整和资源管理来优化系统性能。这个过程不仅需要深入理解Linux系统内部工作原理,还需要...
若要限制大小,例如限制为1MB,可以使用`ulimit -c 1024`。 3. **设置core文件路径和命名规则** - **核心转储文件目录**:`/proc/sys/kernel/core_pattern`决定了core文件的保存位置和文件名。例如,修改为`echo ...
本篇文章将详细介绍在Windows和Linux环境下如何获取和分析系统崩溃日志,以及如何利用GDB进行C++程序的调试。 在Linux系统中,获取程序崩溃信息通常涉及到以下几个步骤: 1. **查询核心转储文件大小**:使用`...