网络推荐



本广告位招租!

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

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

译者:FinalBSD
x a0E6E[jD7y7.1 进程资源和系统限制
.}6I0hwS(YD!Z  为了支持多用户同时登录以及多个应用连接,BSD UNIX系统给系统管理员提供了控制系统资源的许多方法。这种资源限制包括CPU时间、内存使用量以及磁盘使用量。资源控制允许你调整系统到最佳的使用率。UNIX的早期版本中,一些在编译时设置的系统限制如果需要修改,则需要重新编译整个系统。然而,如果并非所有的运行中的系统资源都需要重新编译整个系统,那么现代的BSD系统可以调整大多数这些资源的限制。BSD爱好者乐园 `X?X!Tg

t K(taw9K  本章阐述和进程相关的限制,包括系统端和用户使用的。我们将会看到如何发现这些限制以及怎么修改之,还将阐述进程是如何查询它的资源使用率。
k,iD2G0N6hf*n a
r,no5sO/WBSD爱好者乐园KY&c[Op
7.2  确定系统限制
0}&XE5Y \;`getrlimit,setrlimit
:CA[k!`U:]BSD爱好者乐园p L r1S0E{)m
        getrlimit允许一个进程查询所受的的系统限制.这些系统限制通过一对硬/软限制对来指定。当一个软限制被超过时,进程还可以继续,当然这取决于限制的类型,同时一个信号会发送给进程。另一方面,进程不可以超过它的硬限制。软限制值可以被进程设置在位于0和最大硬限制间的任意值。硬限制值不能被任何进程降低,仅仅超级用户可以增加之。
:gFA:BM[ZE&\
i-n.V#Z$JQ
 
#include <sys/types.h>BSD爱好者乐园c*A%UcU}
          #include <sys/time.h>
:R&U {U)Pl9R Gi          #include <sys/resource.h>
M{:L8m~6V N{
e8x'A"T&Z%g M    int  getrlimit(int resource, struct rlimit *rlp);
xo dpR    int  setrlimit(int resource, const struct rlimit *rlp);
BSD爱好者乐园 S,@%A!nQ^4i;o
getrlimit和setrlimit都使用下面的数据结构:BSD爱好者乐园{ Q TIz#km(fo2k

Lq4Yt Xl _%H
 
struct rlimit {
%Hh_.IG\                rlim_t rlim_cur;
$Y?7OE\                rlim_t rlim_max;
-c8c/Xmy] aO        };

.eqyN"\~z]我们来看每个成员变量。rlim_cur为指定的资源指定当前的系统软限制。rlim_max将为指定的资源指定当前的系统硬限制。
Z T e+x0RNk
j$zI~r,Qx(lnPo        getrlimit和setrlimit函数的第一个参数是资源参数。这个参数用来指定进程获取信息的那个资源。可能的资源值列于下面。你也可以在/usr/include/sys/resource.h中找到它们:BSD爱好者乐园+{9d9\ ]/ML(n.\
BSD爱好者乐园 ^$o)K0k!y3p
 
#define  RLIMIT_CPU  0     /* cpu time in milliseconds */
BSD爱好者乐园p!I+bE `i
RLIMIT_CPU资源限制指定一个进程可以取得CPU执行任务的毫秒数。一般地,一个进程仅仅有一个软限制而没有硬限制。如果超出软限制,进程会收到一个SIGXCPU信号。
6WTW+QVc^BSD爱好者乐园v7ZH Nh+r5IG!]G9A
 
  #define  RLIMIT_FSIZE   1     /* maximum file size */
BSD爱好者乐园DS"T:O9m
RLIMIT_FSIZE限制指定一个进程可以创建的最大文件大小,以字节为单位。比如,如果RLIMIT_FSIZE设置为0,那么进程将根本不能创建文件。如果进程超出此限制,就会发出SIGFSZ信号。BSD爱好者乐园{$_5b*t5{Lv9o3@y
 
#define  RLIMIT_DATA 2     /* data size */
BSD爱好者乐园 D&D KsDmT3z
RLIMIT_DATA 限制指定一个进程数据段可占据的最大字节值。一个进程的数据段就是放置动态内存的一个区域(C/C++中用malloc()分配的内存)。如果超出限制,分配新内存的操作将会遭到失败。BSD爱好者乐园$mE&{Z_:ypuY weQ

%I'}2db9o.Y^ecP
 
#define  RLIMIT_STACK   3     /* stack size */

"f#n+[NOQfRLIMIT_STACK限制指定进程栈可占据的最大字节数。一旦超出硬限制,进程会收到SIGSEV信号。BSD爱好者乐园{%gl[6z
BSD爱好者乐园 ?9D#A7KCu7l^
 
#define  RLIMIT_CORE 4     /* core file size */

!r)Jv^ N%R+A3gRLIMIT_CORE限制指定了进程可以创建的最大core文件的大小。如果此限制设为0,将不能创建。另外,当达到此限制时,所有正在写core文件的进程都将被中断。BSD爱好者乐园e+FK~n5R R2A
BSD爱好者乐园tzNE h{.]
 
#define  RLIMIT_RSS  5     /* resident set size */

L an"^l _r7k2{RMIMIT_RSS限制了进程的常驻集大小(resident set size)可占据的最大字节数.这个进程的常驻集和进程所使用的物理内存数有关。
Qz0H:Q1W&pBSD爱好者乐园"j`irsv\
 
  #define  RLIMIT_MEMLOCK 6     /* locked-in-memory address space */
BSD爱好者乐园'G/m7r/D$QMP
RLIMIT_MEMLOCK限制指定了进程可以使用系统调用到mlock进行锁定的最大字节数。
o4N}t0~SBSD爱好者乐园K#lE'}v
 
  #define  RLIMIT_NPROC   7     /* number of processes */

RUhVqjRLIMIT_NPROC 限制指定了一个指定用户可以开启的最多并发进程数。这里的用户是通过进程来确定的有效用户ID.BSD爱好者乐园| V6b$m!]*nzK

?#L#R&f ~ _5i3qt
 
#define  RLIMIT_NOFILE  8     /* number of open files */

Q{e!`au7g9ARLIMIT_NOFILE 限制指定了进程可以打开的最多文件数。
#c A3|,utwg5_*BBSD爱好者乐园l:]0I5s8x)|9We|$NK
 
  #define  RLIMIT_SBSIZE  9     /* maximum size of all socket buffers */

/V/n.x(i t"N?^ KMwjRLIMIT_SBSIZE限制指定用户在任何时刻可使用的mbufs数。可以查看socket man页来获得mbufs的定义。BSD爱好者乐园"`W {LC7SpB1Y$_8[

LkZmh Z[
 
#define  RLIMIT_VMEM 10    /* virtual process size (inclusive of mmap) */
BSD爱好者乐园2i{:d!} P\J
RLIMIT_VMEM限制说明一个进程的映射地址空间可以占据的字节数。如果超出限制,分配动态内存和到mmap的调用会失败。
v |0ml!H}f\
Ld M,wx$t'LPT&h-y3P b
 
#define  RLIM_INFINITY

k%p E CdY ~ ?RLIM_INFINITY宏用来去除对一个资源的限制。换句话说,将一个资源的硬限制设置为RLIM_INFINITY将会导致此种资源的使用没有任何系统限制。 将软限制设置为RLIM_INFINITY将会阻止进程收到任何软限制警告。如果你的进程不想为那些会导致进程在超过软限制时发送信号的资源设置一个信号处理器,这个参数将变得非常有用。BSD爱好者乐园Fw td#`.X X*w Q|
如果使用了getrlimit参数,那么第二个参数需要设置为一个到rlimit结构的有效指针。然后getrlimit会将适当的限制值放入此结构。另外,在改变限制时,setrlimit会使用在第二个参数中设置值。将值设置为0将会阻止使用此资源。将值设置为RLIM_INFINITY会除去对该资源的所有限制。这些函数都在执行成功后都返回0,反之为-1.有任何错误产生,这些函数会相应的设置errno。BSD爱好者乐园3t(A"k'AC$Cy

u9Q6B,x0Lgetpagesize函数
t7A|wNN~2p
2Rs.i)T'n.Z]8B
 
#include <unistd.h>   BSD爱好者乐园TV7mO?;|
int  getpagesize(void);

J.XT8\'M6Ex  在介绍getrusage函数前,我们需要讨论一下getpagesize函数。一些进程状态 是根据使用的分页(pages)来显示的。分页的内存仅仅是一段内存,通常为4096字节左右。但是分页大小却千差万别,并且它不会固定编入(hard-coded)你的系统。取而代之的是,要确定本地系统的分页大小(pagesize)需要使用getpagesezi函数。getpagesize的返回值就是每个分页使用的字节数。
^])@{|7JF
-eX9vgW Z*f8jt7.3 确定进程资源使用量
['do6I u"hD
*k)j7OBI[SP}getrusage函数  
#PPy7y~(~ w*w   现在我们知道如何查看系统限制,我们还需要知道如何确定当前进程资源的使用量。getrusage函数就是用于此目的。此函数很容易被理解。一个进程可以确定它的内存使用量、CPU执行时间、甚至可获得其子进程的相关信息。因此,getrusage函数的一个用途就是帮助系统避免逃逸进程(runaway)的出现。逃逸进程指的是那些不受系统控制的进程,它们或者使用了过多的CPU(比如循环调用)、或者是超过了内存使用量的限制(导致内存泄漏)。BSD爱好者乐园5u@ |K#X.{A
BSD爱好者乐园Hp;K/M \ {6p(p5n w
 
  #include <sys/types.h>
,G:X'ey-if6j t$@rrV  #include <sys/time.h>
l$MJs'F%C  #include <sys/resource.h>BSD爱好者乐园f O8q*]:J(mo2k(O1A
  BSD爱好者乐园(Vs%P%M;prF[
  #define   RUSAGE_SELF     0
ZTutF b-]O  #define   RUSAGE_CHILDREN     -1
,Z1mM^6u6WLvps  BSD爱好者乐园:W&[ O ?#S
    int   getrusage(int who, struct rusage *rusage);

9GAjjq9dF%sgetrusage函数有两个参数。第一个参数可以设置为RUSAGE_SELF或者RUSAGE_CHILDREN。如果设置成RUSAGE_SELF,那么将会以当前进程的相关信息来填充rusage(数据)结构。反之,如果设置成RUSAGE_CHILDREN,那么rusage结构中的数据都将是当前进程的子进程的信息。BSD爱好者乐园8P$s0`%]&mP"o]
       
.erN(o@ n!Z+|#_ [    rusage(数据)结构定义在/usr/include/sys/resource.h中。它含有以下成员变量:BSD爱好者乐园s%um2wH

,NGfSuB
 
struct   rusage {BSD爱好者乐园$~oU/]FRC
      struct timeval ru_utime;   /* user time used */
1A`)po\h      struct timeval ru_stime;   /* system time used */BSD爱好者乐园pF[v6{,U,Ny
      long  ru_maxrss;           /* max resident set size */
8Y@,T.O1J3Y m)z&U*x      long  ru_ixrss;            /* integral shared memory size */BSD爱好者乐园N)}2qA F+U
      long  ru_idrss;            /* integral unshared data */BSD爱好者乐园-{U#f QA aq _&}`
      long  ru_isrss;            /* integral unshared stack */
^7l p"d1FN.h+Ko/{      long  ru_minflt;           /* page reclaims */BSD爱好者乐园v#[&b;y7Q+U2S6T
      long  ru_majflt;           /* page faults */
e#c"SR+w{&l(\(b      long  ru_nswap;            /* swaps */BSD爱好者乐园y JCu a5Tv'GLwz
      long  ru_inblock;          /* block input operations */BSD爱好者乐园uy r|!^8j,Dg \
      long  ru_oublock;          /* block output operations */
yhj9OL%B!d#u      long  ru_msgsnd;           /* messages sent */BSD爱好者乐园!?,O3raM|qb8I ev
      long  ru_msgrcv;           /* messages received */
8@!{$h\%eQ%M;ny*}      long  ru_nsignals;         /* signals received */
:` ]Sn6~ dp      long  ru_nvcsw;            /* voluntary context switches */BSD爱好者乐园&zMu g_
      long  ru_nivcsw;           /* involuntary " */
,nv_e]9Zi  };
BSD爱好者乐园8\ pKzU$~
我们来详细分析每一个成员变量。BSD爱好者乐园A+vQT*C}
ru_utime,ru_stimeBSD爱好者乐园{$iUQu-JYA.k"{
ru_utime和ru_stime成员变量包含了在用户模式和系统模式中执行时间的总和。它们都使用timeval结构(请查看前一章来了解此结构。)BSD爱好者乐园.B'A u Oe(i:Y3e|![V

I9D:OgEru_maxrssBSD爱好者乐园b R!{8Oxd(Y
ru_maxrss保存了常驻集的内存使用数。其值根据内存分页的使用来确定。
p+{R(} ft2^5K
@6MH kc W xru_ixrssBSD爱好者乐园&|u:N I\9C OE
ru_ixrss值指文本段(text segment)使用的内存数乘以执行滴答数。BSD爱好者乐园yQ:z~*I v
BSD爱好者乐园0j g(T%R\4XVQ
ru_idrss
*uSa}]_ Rru_idrss 值指进程所使用的私有内存数(KB)乘以执行滴答数来。
1B0PK#c m[%w$Dkv
/k*l/pc2y#Vru_isrss
Hx4H9d)PNru_isrss 指栈使用的内存数(KB为单位)乘以执行滴答数。BSD爱好者乐园0U7p7{9I#OxQC]

5r L%@#O1Uru_minflt
;`(XN7Y0|%W aru_minflt值指不需要I/O的页缺失数。页缺失发生在内核需要得到一个内存页以供进程访问时。BSD爱好者乐园smR5X-},]K&P8^

v@9u7Jh9k|ru_majflt
6ry'?m Roru_majflt值指需要I/O的页缺失数。页缺失发生在内核需要得到一个内存页以供进程访问时。BSD爱好者乐园1H0u _?}
BSD爱好者乐园 l%Yf;l#V0w)e0T:Tk,f.E
ru_nswapBSD爱好者乐园9H3f }0W'Ai
有时,一个进程会被调出内存,以提供空间给其他进程使用。ru_nswap指的就是一个进程将要调出内存的次数。BSD爱好者乐园s Y#?I Fz[D
BSD爱好者乐园^ DH-kYO| DR n
ru_inblockBSD爱好者乐园cs"Ji6_|6i;do
ru_inblock 指文件系统需要为一个读请求执行输入操作的次数。
Z#M,u!R;`P,M
9K/W1`)CA\ru_oublock
s)Vm5@z8J9?'@/lru_oublock指文件系统需要为一个写入请求执行输出操作的次数。BSD爱好者乐园 NMP)MQ:l#t0MM7U
BSD爱好者乐园9F9hLXmWU S+t
ru_msgsndBSD爱好者乐园BDC`8nm'B
ru_msgsnd指发送的IPC信息总数
.Wi^!Rmm;w
e.FY~M'x0UQru_msgrcv
vg,BY%A3H\-?lpru_msgrcv指收到的IPC信息总数。
Y2_'@'F { uM
6ai.x1J;[V Rlru_nsignalsBSD爱好者乐园.kUUa;a'v
ru_nsignals指进程收到的信号总数。
$Ow @r [}bx8fBSD爱好者乐园%~L-Wh7Q Mr]9W
ru_nvcswBSD爱好者乐园'MA)J a x:\#]U{0TD
一个进程主动上下文且混总数。主动上下文切换发生在一个进程放弃它的CPU分时时。通常发生在一个进程等待某可用资源时。
8f E%O;yGoq6fH#QBSD爱好者乐园b?1J j.uu
ru_nivcswBSD爱好者乐园.T+Et6o'THgt3e5l
ru_nivcsw包含了因高优先级进程运行导致的上下文切换总数。BSD爱好者乐园C[/C*VY2P
BSD爱好者乐园q Iz+DT7`5s7b
7.4 小结BSD爱好者乐园3y]Fd'Pf*F
本章主要阐述了程序如何得到系统限制。这些限制不应该固定写入你的代码。取而代之的是,你的程序应该使用这些接口。这是因为这些限制是与平台相关的,甚至不同系统间都会有差别。比如,系统管理员可以调整允许打开的最大文件数,因此如果你需要增加或者减小这个值,就不能将值4096固定写入程序中。另一个例子是分页大小。一些64位系统使用8096作为默认的分页大小,但是大多数的32位系统将此默认值设置位4096。再次强调,这是个可调整的参数,不应该使用一个固定的值。BSD爱好者乐园7?5M:s T1u
我们还学习了一个程序如何得到其资源的当前使用量,或者查看其子进程的资源使用状况。使用这些接口可以帮助我们检测甚至避免出现失控的进程。它们用在程序试图超越其软/硬限制时调试错误也非常不错。
[重要提醒]对本篇资料有疑问,请到论坛讨论,尽量使文章准确无误>>>
[版权声明]BSD爱好者乐园站内文章,如来源不是互联网,则均系原创或翻译之作,可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。
TAG: freebsd FreeBSD 系统编程
 

评分:0

我来说两句

seccode