linux ulimit总结(二)–整理自网络

简介:

注:关于文档最好的资源为:man 2 setrlimit

[centosdb@centosDB ~]# ulimit -a

39001479821478.png

35721479821478.png

1、限制进程产生的文件大小(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)普通用户只能缩小硬限制,超级用户可以扩大硬限制(centos72实验结果是,普通用户也不能缩小硬限制)

用普通用户进入系统

su – centosdb

查看创建文件大小的硬限制

ulimit -H –f

unlimited

(网上说可以缩小,在centos72上,实验结果是不能缩小)此时不能缩小该硬限制

ulimit -H -f 1000

-bash: ulimit: file size: cannot modify limit: Invalid argument

但不能扩大该硬限制

ulimit -H -f 10000

4)硬限制控制软限制,软限制来限制用户对资源的使用

用软限制限制创建文件的大小为1000KB

ulimit -S -f 1000

用硬限制限制创建文件的大小为2000KB

ulimit -H -f 2000

创建3MB大小的文件

dd if=/dev/sda1 of=/tmp/test bs=3M count=1

File size limit exceeded (core dumped)

查看/tmp/test的大小为1000KB,说明软限制对资源的控制是起决定性作用的.

ls -lh /tmp/test

-rw-r–r– 1 root root 1000K Nov 21 06:53 /tmp/test

file size单位是KB.

2、关于进程优先级的限制(scheduling priority)

这里的优先级指NICE

这个值只对普通用户起作用,对超级用户不起作用,这个问题是由于CAP_SYS_NICE造成的.

例如调整普通用户可以使用的nice值为-1020之间.

硬限制nice的限制为-1520之间.

ulimit -H -e 35

软限制nice的限制为-1020之间

ulimit -S -e 30

nice命令,使执行lsnice值为-10

nice -n -10 ls /tmp
ssh-BossiP2810 ssh-KITFTp2620 ssh-vIQDXV3333

nice命令,使执行lsnice值为-11,此时超过了ulimitnice的软限制,出现了异常.

nice -n -11 ls /tmp

nice: cannot set niceness: Permission denied

3、内存锁定值的限制(max locked memory)

这个值只对普通用户起作用,对超级用户不起作用。

linux对内存是分页管理的,这意味着有不需要时,在物理内存的数据会被换到交换区或磁盘上.

有需要时会被交换到物理内存,而将数据锁定到物理内存可以避免数据的换入/换出.

采用锁定内存有两个理由:

1)由于程序设计上需要,比如oracle等软件,就需要将数据锁定到物理内存.

2)主要是安全上的需要,比如用户名和密码等等,被交换到swap或磁盘,有泄密的可能,所以一直将其锁定到物理内存.

锁定内存的动作由mlock()函数来完成

mlock的原型如下:

int mlock(const void *addr,size_t len);

测试程序如下:

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>#include<stdlib.h>#include<sys/mman.h>#include <sys/resource.h>#include <sys/time.h>#include <unistd.h>#include <string.h> const int alloc_size = 32 * 1024 ; //分配内存int main() { 
          // Define and object of structure         // rlimit.         struct rlimit rl; 
          getrlimit(RLIMIT_MEMLOCK, &rl); 
          printf ( "\n Default value is : %lld\n" , ( long  long  int ) rl.rlim_cur); 
          // Change the limit         rl.rlim_cur = 31*1024; 
          // Now call setrlimit() to set the         // changed value.         setrlimit(RLIMIT_MEMLOCK, &rl); 
          // Again get the limit and check         getrlimit(RLIMIT_MEMLOCK, &rl); 
          printf ( "\n Default value now is : %lld\n" , ( long  long  int ) rl.rlim_cur); 
          char  *memory =  malloc (alloc_size);          if  (mlock(memory, alloc_size) == -1) {                   perror ( "mlock" );                   return  (-1);         }          size_t  i;          size_t  page_size = getpagesize();          for  (i = 0; i < alloc_size; i += page_size) {                   printf ( "i=%zd\n" ,i);                  memory[i] = 0;         } 
          if  (munlock(memory, alloc_size) == -1) {                   perror ( "munlock" );                   return  (-1);         } 
          return  0;}
1
gcc -o limit_memlock limit_memlock.c

运行结果:

87031479821478.png

以上程序:    rl.rlim_cur的值改成32*1024,也是会报错的,因为程序本身也要使用内存,我改成36*1024就可以正常运行,具体值视环境而定。

4、进程打开文件的限制(open files)

这个值针对所有用户,表示可以在进程中打开的文件数.

例如我们将open files的值改为3

ulimit -n 3

此时打开/etc/passwd文件时失败了.

[root@centosDB ~]# ulimit -n 3

[root@centosDB ~]# cat /etc/passwd

-bash: start_pipeline: pgrp pipe: Too many open files

cat: error while loading shared libraries: libc.so.6: cannot open shared object file: Error 24

c++源代码

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>#include<stdlib.h>#include<sys/mman.h>#include <sys/resource.h>#include <sys/time.h>#include <unistd.h>#include <string.h> const int alloc_size = 32 * 1024 ; //分配内存int main() { 
        // Define and object of structure       // rlimit.       struct rlimit rl; 
        getrlimit(RLIMIT_MEMLOCK, &rl); 
        printf ( "\n Default value is : %lld\n" , ( long  long  int ) rl.rlim_cur); 
        // Change the limit       rl.rlim_cur = 31*1024; 
        // Now call setrlimit() to set the       // changed value.       setrlimit(RLIMIT_MEMLOCK, &rl); 
        // Again get the limit and check       getrlimit(RLIMIT_MEMLOCK, &rl); 
        printf ( "\n Default value now is : %lld\n" , ( long  long  int ) rl.rlim_cur); 
        char  *memory =  malloc (alloc_size);        if  (mlock(memory, alloc_size) == -1) {               perror ( "mlock" );               return  (-1);       }        size_t  i;        size_t  page_size = getpagesize();        for  (i = 0; i < alloc_size; i += page_size) {               printf ( "i=%zd\n" ,i);              memory[i] = 0;       } 
        if  (munlock(memory, alloc_size) == -1) {               perror ( "munlock" );               return  (-1);       } 
        return  0;}

运行结果:

95451479821478.png

5、信号可以被挂起的最大数(pending signals)

这个值针对所有用户,表示可以被挂起/阻塞的最大信号数量

我们用以下的程序进行测试,源程序如下:

1
#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 -o limit_pen_signal limit_pen_signal.c

执行程序limit_pen_signal,这时子程序发送了三次SIGRTMIN信号,父程序在过3秒后,接收并处理该信号.

./limit_pen_signal

parent sleeping

child – BANG!

child – BANG!

child – BANG!

woke up! r=0

handled…

handled…

handled…

exiting

注意:这里有采用的是发送实时信号(SIGRTMIN),:kill(getppid(), SIGRTMIN);

如果不是实时信号,则只能接收一次.

如果我们将pending signals值改为2,这里将只能保证挂起两个信号,第三个信号将被忽略.如下:

[centosdb@centosDB limit_demo]$ ./limit_pen_signal

parent sleeping

child – BANG!

child – BANG!

child – BANG!

woke up! r=0

handled…

handled…

exiting

6可以创建使用POSIX消息队列的最大值,单位为bytes.(POSIX message queues)

我们用下面的程序对POSIX消息队列的限制进行测试,如下:

1
#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);}intmain(int argc, char *argv[]){         struct mq_attr mattr = {                  .mq_maxmsg = 10,                  .mq_msgsize = sizeof(struct message)         };         mqd_t mqid = mq_open("/tmp",                  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("/tmp");         return 0;}

编译:

gcc -o limit_posix_msg limit_posix_msg.c –lrt                                             

限制POSIX消息队列的最大值为1000个字节

ulimit -q 1000                                                                             

这里我们执行test程序

./limit_posix_msg                                                                  

mq_open: Cannot allocate memory                                                      

程序报告无法分配内存.

strace来跟踪limit_posix_msg的运行过程,在下面一条语句时报错.

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                                                                                                                                                

./limit_posix_msg                                                                      

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                                                

7、程序占用CPU的时间,单位是秒(cpu time)

我们用下面的代码对程序占用CPU时间的限制进行测试

源程序如下:

1
2
3
4
5
6
7
8
9
10
#include <sys/resource.h> #include <sys/time.h> #include <unistd.h> #include<stdio.h> 
  int  main () {    // Define and object of structure   // rlimit.   struct rlimit rl; 
    // First get the time limit on CPU   getrlimit (RLIMIT_CPU, &rl); 
    printf ( "\n Default value is : %lld\n" , ( long  long  int )rl.rlim_cur); 
    // Change the time limit   rl.rlim_cur = 1; 
    // Now call setrlimit() to set the   // changed value.   setrlimit (RLIMIT_CPU, &rl); 
    // Again get the limit and check   getrlimit (RLIMIT_CPU, &rl); 
    printf ( "\n Default value now is : %lld\n" , ( long  long  int )rl.rlim_cur); 
    // Simulate a long time consuming work   while (1); 
    return  0; }

[centosdb@centosDB limit_demo]$ ./limit_cpu

 Default value is : 2

 Default value now is : 1

CPU time limit exceeded (core dumped)

8、限制程序实时优先级的范围,只针对普通用户.(real-time priority)

我们用下面的代码对程序实时优先级的范围进行测试

源程序如下:

1
#include<stdio.h>int main(void){       int i;       for (i = 0; i<6; i++)       {              printf("%d\n", i);              sleep(1);       }       return 0;}

编译:

gcc -o limit_rt_priority limit_rt_priority.c

切换到普通用户进行测试

用实时优先级20运行limit_rt_priority程序

chrt -f 20 ./limit_rt_priority

chrt: failed to set pid 0's policy: Operation not permitted

我们用rootulimit的实时优先级调整为20.再进行测试.

su – root

ulimit -r 20

切换到普通用户,用实时优先级20运行程序,可以运行这个程序了.

su – centosdb

[centosdb@centosDB limit_demo]$  chrt -f 20 ./limit_rt_priority

0

1

2

3

4

5

以实时优先级50运行程序,还是报错,说明ulimit的限制起了作用.

chrt -f 50 ./limit_rt_priority

chrt: failed to set pid 0's policy: Operation not permitted

9、限制程序可以fork的进程数,只对普通用户有效(max user processes)

源代码:

1
2
3
4
5
6
7
8
9
10
/*
  * limit_process.c
  *
  *  Created on: Nov 21, 2016
  *      Author: root
  */ #include <sys/resource.h>#include <sys/ time .h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>  int  main (){   // Define and object of structure  // rlimit.  struct rlimit rl; 
   // First get the limit on number of child processes  getrlimit (RLIMIT_NPROC, &rl); 
   printf ( "\n Default value is : %lld\n" , ( long  long  int )rl.rlim_cur); 
   // Change the limit  rl.rlim_cur = 0; // Now we do not want this process to have any child process  rl.rlim_max=0; 
   // Now call setrlimit() to set the  // changed value.  setrlimit (RLIMIT_NPROC, &rl);  // Again get the limit and check  getrlimit (RLIMIT_NPROC, &rl);  printf("\n Default value now is : %lld,max is :%lld\n", (long long int)rl.rlim_cur,(long long int)rl.rlim_max);  // Try creating a process  if( -1 == fork())  {      printf("\n Creating a child process failed\n");  }  return 0;}

结果:

99551479821478.png

10、限制core文件的大小(core file size)

我们用下面的代码对程序生成core的大小进行测试

源代码:

1
#include <stdio.h>static void sub(void);int main(void){       sub();       return 0;} static void sub(void){       int *p = NULL;       printf("%d", *p);}

编译:

gcc -o limit_core limit_core.c

运行程序test,出现段错误.

./limit_core

Segmentation fault (core dumped)

如果在当前目录下没有core文件,我们应该调整ulimitcore的大小进行限制,如果core文件大小在这里指定为0,将不会产生core文件.

这里设定core文件大小为10blocks.:一个blocks在这里为1024个字节.

ulimit -c 10

再次运行这个程序

./limit_core

Segmentation fault (core dumped)

查看core文件的大小

ls -lh core.43308

-rw——- 1 centosdb centosdb 12K Nov 21 08:00 core.43308

我们设定10blocks应该是10*1024也不是10KB,为什么它是12KB,因为它的递增是4KB.

如果调整到14blocks,我们将最大产生16KBcore文件.

11、限制进程使用数据段的大小(data seg size)

一般来说这个限制会影响程序调用brk(系统调用)sbrk(库函数)

调用malloc时,如果发现vm不够了就会用brk去内核申请.

我们这里用一个测试程序对data segment的限制进行测试.

源程序如下:

1
#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 -o limit_data_seg limit_data_seg.c

./ limit_data_seg

hello I used 0 vmemory

通过ulimit将限制改为170KB

再次运行程序

./limit_data_seg

hello I used 167936 vmemory

12、限制进程使用堆栈段的大小

我们用ulimit将堆栈段的大小调整为16,16*1024.

ulimit -s 16

再运行命令:

ls -l /etc/

total 1480

Segmentation fault (core dumped)

13、限制进程使用虚拟内存的大小

我们用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

14、剩下的三种ulimit限制说明(file locks/max memory size/pipe size)

文件锁的限制只在2.4内核之前有用.

驻留内存的限制在很多系统里也没有作用.

管道的缓存不能改变,只能是8*512(bytes),也就是4096个字节.



本文转自 corasql 51CTO博客,原文链接:http://blog.51cto.com/corasql/1905353,如需转载请自行联系原作者

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
16天前
|
安全 Linux 虚拟化
网络名称空间在Linux虚拟化技术中的位置
网络名称空间(Network Namespaces)是Linux内核特性之一,提供了隔离网络环境的能力,使得每个网络名称空间都拥有独立的网络设备、IP地址、路由表、端口号范围以及iptables规则等。这一特性在Linux虚拟化技术中占据了核心位置🌟,它不仅为构建轻量级虚拟化解决方案(如容器📦)提供了基础支持,也在传统的虚拟机技术中发挥作用,实现资源隔离和网络虚拟化。
网络名称空间在Linux虚拟化技术中的位置
|
16天前
|
网络协议 安全 Linux
Linux网络名称空间之独立网络资源管理
Linux网络名称空间是一种强大的虚拟化技术🛠️,它允许用户创建隔离的网络环境🌐,每个环境拥有独立的网络资源和配置。这项技术对于云计算☁️、容器化应用📦和网络安全🔒等领域至关重要。本文将详细介绍在Linux网络名称空间中可以拥有的独立网络资源,并指出应用开发人员在使用时应注意的重点。
|
16天前
|
安全 网络协议 Linux
Linux网络名称空间概述
Linux网络名称空间是操作系统级别的一种虚拟化技术🔄,它允许创建隔离的网络环境🌐,使得每个环境拥有自己独立的网络资源,如IP地址📍、路由表🗺️、防火墙规则🔥等。这种技术是Linux内核功能的一部分,为不同的用户空间进程提供了一种创建和使用独立网络协议栈的方式。本文旨在全方面、多维度解释Linux网络名称空间的概念、必要性和作用。
Linux网络名称空间概述
|
14天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
38 6
|
5天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
17天前
|
网络协议 Linux
在Linux中,管理和配置网络接口
在Linux中管理网络接口涉及多个命令,如`ifconfig`(在新版本中被`ip`取代)、`ip`(用于网络设备配置)、`nmcli`(NetworkManager的CLI工具)、`nmtui`(文本界面配置)、`route/ip route`(处理路由表)、`netstat/ss`(显示网络状态)和`hostnamectl/systemctl`(主机名和服务管理)。这些命令帮助用户启动接口、设置IP地址、查看连接和路由信息。不同发行版可能有差异,建议参考相应文档。
19 4
|
2天前
|
网络协议 Linux Shell
【linux网络(一)】初识网络, 理解四层网络模型
【linux网络(一)】初识网络, 理解四层网络模型
|
2天前
|
安全 Ubuntu Linux
Linux 网络操作命令Telnet
Linux 网络操作命令Telnet
16 0
Linux 网络操作命令Telnet
|
3天前
|
Ubuntu Linux
Linux(22) Linux设置网络优先级顺序
Linux(22) Linux设置网络优先级顺序
5 0
|
4天前
|
Ubuntu 网络协议 Linux
Linux(20) Ubuntu 20.04 网络接口自动切换路由配置
Linux(20) Ubuntu 20.04 网络接口自动切换路由配置
27 0