网络推荐

推荐给好友 上一篇 | 下一篇

第七章: 进程资源和系统限制

译者:FinalBSDBSD爱好者乐园b(_9l/j_M5{
7.1 进程资源和系统限制
C5QB l7V3T3Jy  为了支持多用户同时登录以及多个应用连接,BSD UNIX系统给系统管理员提供了控制系统资源的许多方法。这种资源限制包括CPU时间、内存使用量以及磁盘使用量。资源控制允许你调整系统到最佳的使用率。UNIX的早期版本中,一些在编译时设置的系统限制如果需要修改,则需要重新编译整个系统。然而,如果并非所有的运行中的系统资源都需要重新编译整个系统,那么现代的BSD系统可以调整大多数这些资源的限制。
5P] gWHz/g1TBSD爱好者乐园IRg ]0~3r,z1lm
  本章阐述和进程相关的限制,包括系统端和用户使用的。我们将会看到如何发现这些限制以及怎么修改之,还将阐述进程是如何查询它的资源使用率。
-vCY(O,qL+E/v
)~H1Al6B%J y3z%CBSD爱好者乐园[Wsauyl[}
7.2  确定系统限制BSD爱好者乐园pz(h&f0X|BW.r
getrlimit,setrlimit
xC-`%Lkug-NP&Q%\BSD爱好者乐园DTo&jF-h9I1F
        getrlimit允许一个进程查询所受的的系统限制.这些系统限制通过一对硬/软限制对来指定。当一个软限制被超过时,进程还可以继续,当然这取决于限制的类型,同时一个信号会发送给进程。另一方面,进程不可以超过它的硬限制。软限制值可以被进程设置在位于0和最大硬限制间的任意值。硬限制值不能被任何进程降低,仅仅超级用户可以增加之。BSD爱好者乐园l)M+EpX5pF.GQ

0`4a1Co Q ^u
 
#include <sys/types.h>
1j!~,ci ` C)Y          #include <sys/time.h>
WL"or3]v          #include <sys/resource.h>
2O;D([:_l V4j2n,trq
dw[2~8Ju$T&q    int  getrlimit(int resource, struct rlimit *rlp);BSD爱好者乐园"Yj7t*v5@w
    int  setrlimit(int resource, const struct rlimit *rlp);
BSD爱好者乐园N1J"][Q!x0s\9I
getrlimit和setrlimit都使用下面的数据结构:
g2B F']i}3RBSD爱好者乐园4~;](Us mSR:K_ y5T
 
struct rlimit {
#b#zH7D;YZ                rlim_t rlim_cur;BSD爱好者乐园~;m2W$j]t nM8g
                rlim_t rlim_max;
i#DLO&`g o a+?G8w        };
BSD爱好者乐园w&i9Z,PXK
我们来看每个成员变量。rlim_cur为指定的资源指定当前的系统软限制。rlim_max将为指定的资源指定当前的系统硬限制。
1?!B&@`P/k;l
h^2xY-Z*dVn*n        getrlimit和setrlimit函数的第一个参数是资源参数。这个参数用来指定进程获取信息的那个资源。可能的资源值列于下面。你也可以在/usr/include/sys/resource.h中找到它们:BSD爱好者乐园0z,D})A1T,p
BSD爱好者乐园 P%B&St8wWaR
 
#define  RLIMIT_CPU  0     /* cpu time in milliseconds */
BSD爱好者乐园!t/^Sbp
RLIMIT_CPU资源限制指定一个进程可以取得CPU执行任务的毫秒数。一般地,一个进程仅仅有一个软限制而没有硬限制。如果超出软限制,进程会收到一个SIGXCPU信号。BSD爱好者乐园OcB{#v?7f[

Y|)enM1|9]p
 
  #define  RLIMIT_FSIZE   1     /* maximum file size */
BSD爱好者乐园BkR+vVG
RLIMIT_FSIZE限制指定一个进程可以创建的最大文件大小,以字节为单位。比如,如果RLIMIT_FSIZE设置为0,那么进程将根本不能创建文件。如果进程超出此限制,就会发出SIGFSZ信号。
Z.DDP @5nm*[]
 
#define  RLIMIT_DATA 2     /* data size */
BSD爱好者乐园0{,N @"Io4],Y_3\
RLIMIT_DATA 限制指定一个进程数据段可占据的最大字节值。一个进程的数据段就是放置动态内存的一个区域(C/C++中用malloc()分配的内存)。如果超出限制,分配新内存的操作将会遭到失败。BSD爱好者乐园2b&uV0J ?5B"Xc
BSD爱好者乐园2wztNs4zu
 
#define  RLIMIT_STACK   3     /* stack size */
BSD爱好者乐园QX0f;b;n2s
RLIMIT_STACK限制指定进程栈可占据的最大字节数。一旦超出硬限制,进程会收到SIGSEV信号。BSD爱好者乐园#yFg-h{fi;|

4_ b_;j|n
 
#define  RLIMIT_CORE 4     /* core file size */
BSD爱好者乐园*b N S8Z}4^
RLIMIT_CORE限制指定了进程可以创建的最大core文件的大小。如果此限制设为0,将不能创建。另外,当达到此限制时,所有正在写core文件的进程都将被中断。BSD爱好者乐园w M0DU X

9[3p+x,yGK;i
 
#define  RLIMIT_RSS  5     /* resident set size */

\ g#}h ` ?3u~3RKRMIMIT_RSS限制了进程的常驻集大小(resident set size)可占据的最大字节数.这个进程的常驻集和进程所使用的物理内存数有关。
U6rYM \8\~pB
&BE.fd4E"M]%gx
 
  #define  RLIMIT_MEMLOCK 6     /* locked-in-memory address space */

9S&Ryt7COlERLIMIT_MEMLOCK限制指定了进程可以使用系统调用到mlock进行锁定的最大字节数。BSD爱好者乐园 c.f{l3L P

wY5l5_o
 
  #define  RLIMIT_NPROC   7     /* number of processes */
BSD爱好者乐园;J8A%X Z$W
RLIMIT_NPROC 限制指定了一个指定用户可以开启的最多并发进程数。这里的用户是通过进程来确定的有效用户ID.BSD爱好者乐园QO DAY!gLZ'v~

g8D$tdtw(P"s+wP
 
#define  RLIMIT_NOFILE  8     /* number of open files */

| Kq O+w(PQRLIMIT_NOFILE 限制指定了进程可以打开的最多文件数。
B` VR4K#TBSD爱好者乐园fW%F[ KS.r%IO.r
 
  #define  RLIMIT_SBSIZE  9     /* maximum size of all socket buffers */
BSD爱好者乐园.x+y,J7m"g!~E
RLIMIT_SBSIZE限制指定用户在任何时刻可使用的mbufs数。可以查看socket man页来获得mbufs的定义。
:pC0Gd1_jRB
-K4@],I @P wA
 
#define  RLIMIT_VMEM 10    /* virtual process size (inclusive of mmap) */
BSD爱好者乐园7Cm8K@/oX+d9{EE:N
RLIMIT_VMEM限制说明一个进程的映射地址空间可以占据的字节数。如果超出限制,分配动态内存和到mmap的调用会失败。BSD爱好者乐园^&p&p8bcE

8P5m#D}6bkp
 
#define  RLIM_INFINITY

{/G e5qXGRLIM_INFINITY宏用来去除对一个资源的限制。换句话说,将一个资源的硬限制设置为RLIM_INFINITY将会导致此种资源的使用没有任何系统限制。 将软限制设置为RLIM_INFINITY将会阻止进程收到任何软限制警告。如果你的进程不想为那些会导致进程在超过软限制时发送信号的资源设置一个信号处理器,这个参数将变得非常有用。BSD爱好者乐园Bo i Jt%A
如果使用了getrlimit参数,那么第二个参数需要设置为一个到rlimit结构的有效指针。然后getrlimit会将适当的限制值放入此结构。另外,在改变限制时,setrlimit会使用在第二个参数中设置值。将值设置为0将会阻止使用此资源。将值设置为RLIM_INFINITY会除去对该资源的所有限制。这些函数都在执行成功后都返回0,反之为-1.有任何错误产生,这些函数会相应的设置errno。BSD爱好者乐园:Jy#Ug&Qp4k
BSD爱好者乐园 j^9V:zvB
getpagesize函数BSD爱好者乐园#["QN*~1I/KfIWf
BSD爱好者乐园)J c&D5q \X1s
 
#include <unistd.h>   
8REA6{nB/]int  getpagesize(void);
BSD爱好者乐园d%q0u.q|c*L:Sh
  在介绍getrusage函数前,我们需要讨论一下getpagesize函数。一些进程状态 是根据使用的分页(pages)来显示的。分页的内存仅仅是一段内存,通常为4096字节左右。但是分页大小却千差万别,并且它不会固定编入(hard-coded)你的系统。取而代之的是,要确定本地系统的分页大小(pagesize)需要使用getpagesezi函数。getpagesize的返回值就是每个分页使用的字节数。
Q a8Wi s{eBSD爱好者乐园$g2S;~-O IfTD
7.3 确定进程资源使用量
F\ ]r@(k GS tU&m nBSD爱好者乐园D&z/S} M E
getrusage函数  BSD爱好者乐园fy\5y5h[Kwu
   现在我们知道如何查看系统限制,我们还需要知道如何确定当前进程资源的使用量。getrusage函数就是用于此目的。此函数很容易被理解。一个进程可以确定它的内存使用量、CPU执行时间、甚至可获得其子进程的相关信息。因此,getrusage函数的一个用途就是帮助系统避免逃逸进程(runaway)的出现。逃逸进程指的是那些不受系统控制的进程,它们或者使用了过多的CPU(比如循环调用)、或者是超过了内存使用量的限制(导致内存泄漏)。
$BHGvl5YtBSD爱好者乐园Be;QN5`L7Pb-J
 
  #include <sys/types.h>
v`6c9GD6g  #include <sys/time.h>BSD爱好者乐园AfiUS/O*O
  #include <sys/resource.h>BSD爱好者乐园5JO%vhC t
  BSD爱好者乐园:e)U:[ C'YO)a0v
  #define   RUSAGE_SELF     0
B[v0?q  #define   RUSAGE_CHILDREN     -1
XOv?F"m'RCSg  
k&pYr3?    int   getrusage(int who, struct rusage *rusage);
BSD爱好者乐园 IfB b-?
getrusage函数有两个参数。第一个参数可以设置为RUSAGE_SELF或者RUSAGE_CHILDREN。如果设置成RUSAGE_SELF,那么将会以当前进程的相关信息来填充rusage(数据)结构。反之,如果设置成RUSAGE_CHILDREN,那么rusage结构中的数据都将是当前进程的子进程的信息。
2^#?(kR%]vF       
l h2Dtp Dy    rusage(数据)结构定义在/usr/include/sys/resource.h中。它含有以下成员变量:
Y:H5LO d/zBSD爱好者乐园G,yIz g~
 
struct   rusage {BSD爱好者乐园AeV'JT5XV R*y+x
      struct timeval ru_utime;   /* user time used */
2U"];f'YEJ      struct timeval ru_stime;   /* system time used */
X XJ#}*oc.}z&@9^G      long  ru_maxrss;           /* max resident set size */BSD爱好者乐园 b ?G'G%r,W
      long  ru_ixrss;            /* integral shared memory size */BSD爱好者乐园N!}o`6J6zX)x
      long  ru_idrss;            /* integral unshared data */
8jjn3sjy-\-ri      long  ru_isrss;            /* integral unshared stack */
i7e%w\W Nl:J      long  ru_minflt;           /* page reclaims */
)xX'zTTl$l4zgx l      long  ru_majflt;           /* page faults */
~?Ef4quZ}      long  ru_nswap;            /* swaps */BSD爱好者乐园6V6v![5U^6W
      long  ru_inblock;          /* block input operations */BSD爱好者乐园_.W2j H$M6L K
      long  ru_oublock;          /* block output operations */
&z+]"Zq&do!j      long  ru_msgsnd;           /* messages sent */BSD爱好者乐园fkC!\1P"s:ut&VK
      long  ru_msgrcv;           /* messages received */
_o;mLTW T+M:H\1z      long  ru_nsignals;         /* signals received */BSD爱好者乐园f,w.Hwz6p#eZ5|H#EY0o
      long  ru_nvcsw;            /* voluntary context switches */
N V:{7MST      long  ru_nivcsw;           /* involuntary " */
m6u(S X+g*G;L3kj  };
BSD爱好者乐园(F$E6t"r1Q*t,Q-G
我们来详细分析每一个成员变量。BSD爱好者乐园gPxpI5E x n
ru_utime,ru_stimeBSD爱好者乐园 L$d3b9nm~B3e n
ru_utime和ru_stime成员变量包含了在用户模式和系统模式中执行时间的总和。它们都使用timeval结构(请查看前一章来了解此结构。)
ggaU1WBSD爱好者乐园 orxD*g+tKK
ru_maxrss
-Mm`Z2WB\ V'tjru_maxrss保存了常驻集的内存使用数。其值根据内存分页的使用来确定。BSD爱好者乐园:?#x4H q`x\
BSD爱好者乐园C1puMA_3?;k;h/w/Kz{
ru_ixrssBSD爱好者乐园:Fs$r*oEr
ru_ixrss值指文本段(text segment)使用的内存数乘以执行滴答数。BSD爱好者乐园@l%z4a1v
BSD爱好者乐园$@6S4b+G8S\ Yw*YL e
ru_idrss
e%h+S!X7@4orru_idrss 值指进程所使用的私有内存数(KB)乘以执行滴答数来。BSD爱好者乐园yJi iD#n1`f$s-Z5L2['O
BSD爱好者乐园NC4U#a u3p L8vo8f/T,u
ru_isrss
!N*b8w8nn nD(~z.Rru_isrss 指栈使用的内存数(KB为单位)乘以执行滴答数。BSD爱好者乐园GdO {2h]iC2q
BSD爱好者乐园d3e'|Fu:T#s
ru_minflt
%E XDw#f@9MEru_minflt值指不需要I/O的页缺失数。页缺失发生在内核需要得到一个内存页以供进程访问时。
Xw O [H[
}'P?a/n)Iru_majflt
oqEx ]"Kru_majflt值指需要I/O的页缺失数。页缺失发生在内核需要得到一个内存页以供进程访问时。
6Z3^ xn2G#M%{BSD爱好者乐园P:_3L)C`"|
ru_nswapBSD爱好者乐园)hRn2v+A p
有时,一个进程会被调出内存,以提供空间给其他进程使用。ru_nswap指的就是一个进程将要调出内存的次数。BSD爱好者乐园 XM6I Q(@ l8?
BSD爱好者乐园8};h"M JEsX$}yy.t T
ru_inblock
;T4g#Uvh F7_*|ru_inblock 指文件系统需要为一个读请求执行输入操作的次数。
.`0R C^/uju\
3a2^CZ~ cru_oublock
L BB;T~3Dz/bEru_oublock指文件系统需要为一个写入请求执行输出操作的次数。
G3wQ%`8E ~BSD爱好者乐园*W8j^g~,\2K
ru_msgsnd
O0s:?-E6W'n|6iW6aZru_msgsnd指发送的IPC信息总数
-o?%qfc/c
ove0~ HD#pQ Miru_msgrcvBSD爱好者乐园0i%is] J
ru_msgrcv指收到的IPC信息总数。BSD爱好者乐园/r8Ii3jB+F.Z yB
BSD爱好者乐园 n4n$Ub%} b.Qt!A
ru_nsignals
Bj:gyO*H7D(~PTru_nsignals指进程收到的信号总数。
k/ja\6jo rn
eJ-?1]*|hru_nvcswBSD爱好者乐园2xRt#O3y1ek Oc M
一个进程主动上下文且混总数。主动上下文切换发生在一个进程放弃它的CPU分时时。通常发生在一个进程等待某可用资源时。
lG&Yo5T;^iJ^BSD爱好者乐园FV*w#d#I;~/B@8hn];B!d
ru_nivcswBSD爱好者乐园!D2? PVX#Vkl't
ru_nivcsw包含了因高优先级进程运行导致的上下文切换总数。BSD爱好者乐园C"k/Cd*n+@
BSD爱好者乐园 oP,z"O2uj
7.4 小结
vw'n,rR`本章主要阐述了程序如何得到系统限制。这些限制不应该固定写入你的代码。取而代之的是,你的程序应该使用这些接口。这是因为这些限制是与平台相关的,甚至不同系统间都会有差别。比如,系统管理员可以调整允许打开的最大文件数,因此如果你需要增加或者减小这个值,就不能将值4096固定写入程序中。另一个例子是分页大小。一些64位系统使用8096作为默认的分页大小,但是大多数的32位系统将此默认值设置位4096。再次强调,这是个可调整的参数,不应该使用一个固定的值。
m[1_+m$] X?ym我们还学习了一个程序如何得到其资源的当前使用量,或者查看其子进程的资源使用状况。使用这些接口可以帮助我们检测甚至避免出现失控的进程。它们用在程序试图超越其软/硬限制时调试错误也非常不错。因为使用范围的限制,BSD方面文章更新速度不快,站长会坚持每天更新博客,欢迎访问!
[版权声明]BSD爱好者乐园站内文章,如来源不是互联网,则均系原创或翻译之作,可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。
TAG: freebsd FreeBSD 系统编程
 

评分:0

我来说两句

seccode