网络推荐

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

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

译者:FinalBSD
mR@}'y\$t7.1 进程资源和系统限制BSD爱好者乐园}5~ A\e4Rn8Q5Q
  为了支持多用户同时登录以及多个应用连接,BSD UNIX系统给系统管理员提供了控制系统资源的许多方法。这种资源限制包括CPU时间、内存使用量以及磁盘使用量。资源控制允许你调整系统到最佳的使用率。UNIX的早期版本中,一些在编译时设置的系统限制如果需要修改,则需要重新编译整个系统。然而,如果并非所有的运行中的系统资源都需要重新编译整个系统,那么现代的BSD系统可以调整大多数这些资源的限制。BSD爱好者乐园KG.\ G{R
BSD爱好者乐园 `aXZ0J1u
  本章阐述和进程相关的限制,包括系统端和用户使用的。我们将会看到如何发现这些限制以及怎么修改之,还将阐述进程是如何查询它的资源使用率。
c"Z:Rl3o
xOC*q&Nx$fBSD爱好者乐园$y(wO)G8G^7v'z,o
7.2  确定系统限制BSD爱好者乐园7t+g;\hq)v*L
getrlimit,setrlimit
uCP Nz'X jZBSD爱好者乐园(Rz(~Q FL;\!F
        getrlimit允许一个进程查询所受的的系统限制.这些系统限制通过一对硬/软限制对来指定。当一个软限制被超过时,进程还可以继续,当然这取决于限制的类型,同时一个信号会发送给进程。另一方面,进程不可以超过它的硬限制。软限制值可以被进程设置在位于0和最大硬限制间的任意值。硬限制值不能被任何进程降低,仅仅超级用户可以增加之。BSD爱好者乐园;\1H3?Q v%|2|9`BH

m,u-tZn#h i
 
#include <sys/types.h>
w0\2E(?3G:wFsJ"~pt          #include <sys/time.h>BSD爱好者乐园s2n @Hq9yett
          #include <sys/resource.h>BSD爱好者乐园n)^zy zk

XF)L7F4\8x    int  getrlimit(int resource, struct rlimit *rlp);
k7c&Qr8V,F0lY    int  setrlimit(int resource, const struct rlimit *rlp);
BSD爱好者乐园OgO;X+V
getrlimit和setrlimit都使用下面的数据结构:
H8XjCsLOn
mw"G NsS
 
struct rlimit {
X)jg5nXgE P                rlim_t rlim_cur;
H/rz#y tn/P                rlim_t rlim_max;BSD爱好者乐园X^3\q?b&P@
        };

U4{F&b|9|我们来看每个成员变量。rlim_cur为指定的资源指定当前的系统软限制。rlim_max将为指定的资源指定当前的系统硬限制。BSD爱好者乐园-Qr| hB
BSD爱好者乐园8p y7Tg|#l
        getrlimit和setrlimit函数的第一个参数是资源参数。这个参数用来指定进程获取信息的那个资源。可能的资源值列于下面。你也可以在/usr/include/sys/resource.h中找到它们:BSD爱好者乐园 vij"wrr1M@ANG
BSD爱好者乐园.t7^0Tu Kl_j
 
#define  RLIMIT_CPU  0     /* cpu time in milliseconds */
BSD爱好者乐园e`5bMc j+p B
RLIMIT_CPU资源限制指定一个进程可以取得CPU执行任务的毫秒数。一般地,一个进程仅仅有一个软限制而没有硬限制。如果超出软限制,进程会收到一个SIGXCPU信号。
J6O |6O.t!cj7I1y,|
^ ~z0G \M G,?_
 
  #define  RLIMIT_FSIZE   1     /* maximum file size */

&Ga4?9Z0o3ye'x0@FeRLIMIT_FSIZE限制指定一个进程可以创建的最大文件大小,以字节为单位。比如,如果RLIMIT_FSIZE设置为0,那么进程将根本不能创建文件。如果进程超出此限制,就会发出SIGFSZ信号。
U'_7U x/N U;C^5n
 
#define  RLIMIT_DATA 2     /* data size */
BSD爱好者乐园#w9]7???Gv
RLIMIT_DATA 限制指定一个进程数据段可占据的最大字节值。一个进程的数据段就是放置动态内存的一个区域(C/C++中用malloc()分配的内存)。如果超出限制,分配新内存的操作将会遭到失败。BSD爱好者乐园n#IC8XpfYU

"{@|Nbf(aQ
 
#define  RLIMIT_STACK   3     /* stack size */

L*oh2M4Y{RLIMIT_STACK限制指定进程栈可占据的最大字节数。一旦超出硬限制,进程会收到SIGSEV信号。
%W4L Z\]YhBSD爱好者乐园C.[ uW1N\d
 
#define  RLIMIT_CORE 4     /* core file size */
BSD爱好者乐园9xb R8w$N6w
RLIMIT_CORE限制指定了进程可以创建的最大core文件的大小。如果此限制设为0,将不能创建。另外,当达到此限制时,所有正在写core文件的进程都将被中断。BSD爱好者乐园*I,AS m(q'K

8^9l-k2S0h$@t8A
 
#define  RLIMIT_RSS  5     /* resident set size */

4eewNP } QeRMIMIT_RSS限制了进程的常驻集大小(resident set size)可占据的最大字节数.这个进程的常驻集和进程所使用的物理内存数有关。
R cZu@P(`LMBSD爱好者乐园^~y&_)d!c"\
 
  #define  RLIMIT_MEMLOCK 6     /* locked-in-memory address space */

R#JN*b*r _Ml4~nRLIMIT_MEMLOCK限制指定了进程可以使用系统调用到mlock进行锁定的最大字节数。BSD爱好者乐园4~a/H7mq

%PD*oCj%Q
 
  #define  RLIMIT_NPROC   7     /* number of processes */
BSD爱好者乐园$BPQ2~d
RLIMIT_NPROC 限制指定了一个指定用户可以开启的最多并发进程数。这里的用户是通过进程来确定的有效用户ID.
2S%x4caYC
{!v4rq#?
 
#define  RLIMIT_NOFILE  8     /* number of open files */

7L3~`1ch{~6kRLIMIT_NOFILE 限制指定了进程可以打开的最多文件数。
_@&^\1H!C
{/^H3F9eN!T
 
  #define  RLIMIT_SBSIZE  9     /* maximum size of all socket buffers */
BSD爱好者乐园T@!PxY8UKC
RLIMIT_SBSIZE限制指定用户在任何时刻可使用的mbufs数。可以查看socket man页来获得mbufs的定义。
8WQj%r0F.e&|5iBSD爱好者乐园 iL)P8M8K {.m V
 
#define  RLIMIT_VMEM 10    /* virtual process size (inclusive of mmap) */

wtC#}(O'zS:LHRLIMIT_VMEM限制说明一个进程的映射地址空间可以占据的字节数。如果超出限制,分配动态内存和到mmap的调用会失败。
l9t_2U3Y#w2cN uk
oeC,] u^
 
#define  RLIM_INFINITY
BSD爱好者乐园_3H? p@5T*F
RLIM_INFINITY宏用来去除对一个资源的限制。换句话说,将一个资源的硬限制设置为RLIM_INFINITY将会导致此种资源的使用没有任何系统限制。 将软限制设置为RLIM_INFINITY将会阻止进程收到任何软限制警告。如果你的进程不想为那些会导致进程在超过软限制时发送信号的资源设置一个信号处理器,这个参数将变得非常有用。
\(LO)wqn(K如果使用了getrlimit参数,那么第二个参数需要设置为一个到rlimit结构的有效指针。然后getrlimit会将适当的限制值放入此结构。另外,在改变限制时,setrlimit会使用在第二个参数中设置值。将值设置为0将会阻止使用此资源。将值设置为RLIM_INFINITY会除去对该资源的所有限制。这些函数都在执行成功后都返回0,反之为-1.有任何错误产生,这些函数会相应的设置errno。BSD爱好者乐园HzzBI4pNe5O

{y/SY Jp0Hgetpagesize函数
u"\ge.R2LS ]!y#NBSD爱好者乐园 K2[/Mx:kX,I
 
#include <unistd.h>   
vQfcpzint  getpagesize(void);
BSD爱好者乐园8~f:W;_d)ot+Ot
  在介绍getrusage函数前,我们需要讨论一下getpagesize函数。一些进程状态 是根据使用的分页(pages)来显示的。分页的内存仅仅是一段内存,通常为4096字节左右。但是分页大小却千差万别,并且它不会固定编入(hard-coded)你的系统。取而代之的是,要确定本地系统的分页大小(pagesize)需要使用getpagesezi函数。getpagesize的返回值就是每个分页使用的字节数。
"Yb)B8T&Dz
} _&_ROOT7.3 确定进程资源使用量BSD爱好者乐园)} Q hw L%@
BSD爱好者乐园%z1Z8`0X|G/z"|
getrusage函数  BSD爱好者乐园XQ1W%|`M-\KX
   现在我们知道如何查看系统限制,我们还需要知道如何确定当前进程资源的使用量。getrusage函数就是用于此目的。此函数很容易被理解。一个进程可以确定它的内存使用量、CPU执行时间、甚至可获得其子进程的相关信息。因此,getrusage函数的一个用途就是帮助系统避免逃逸进程(runaway)的出现。逃逸进程指的是那些不受系统控制的进程,它们或者使用了过多的CPU(比如循环调用)、或者是超过了内存使用量的限制(导致内存泄漏)。BSD爱好者乐园)T3dt%T Rw [4s

Y#P0H"o&AeJ&v/g4L
 
  #include <sys/types.h>BSD爱好者乐园2{RG1t4{N E c-H
  #include <sys/time.h>
(~wQ$P$c_*C  #include <sys/resource.h>BSD爱好者乐园*xG c D8Y
  
7m6`q'|?{9j  #define   RUSAGE_SELF     0
P)q9i CN[O'G*|%N],E  #define   RUSAGE_CHILDREN     -1
9EO2j)R0s$EC  BSD爱好者乐园(HNvFdSr
    int   getrusage(int who, struct rusage *rusage);
BSD爱好者乐园a)w/j&L2z-K+a;Yb
getrusage函数有两个参数。第一个参数可以设置为RUSAGE_SELF或者RUSAGE_CHILDREN。如果设置成RUSAGE_SELF,那么将会以当前进程的相关信息来填充rusage(数据)结构。反之,如果设置成RUSAGE_CHILDREN,那么rusage结构中的数据都将是当前进程的子进程的信息。
l/^ Q(FDw_7I       
~he rI(UM5U&k    rusage(数据)结构定义在/usr/include/sys/resource.h中。它含有以下成员变量:BSD爱好者乐园Hk?KT0S.Z7X"w

Ihc'Kg p |4f
 
struct   rusage {BSD爱好者乐园9m['P*R)~y
      struct timeval ru_utime;   /* user time used */BSD爱好者乐园}c!b!uAUM3G5L
      struct timeval ru_stime;   /* system time used */BSD爱好者乐园 i,s t!pjh
      long  ru_maxrss;           /* max resident set size */BSD爱好者乐园$AE}8j DY
      long  ru_ixrss;            /* integral shared memory size */
ho%Ae6YH!q      long  ru_idrss;            /* integral unshared data */
M Cgnxr$s;y C,e/utv      long  ru_isrss;            /* integral unshared stack */
RW1C(g&O'taVS      long  ru_minflt;           /* page reclaims */
2xY \D,v"|D$X^k?      long  ru_majflt;           /* page faults */
,^!m mj;tspM      long  ru_nswap;            /* swaps */
8v;b-gf})?2^2[2R      long  ru_inblock;          /* block input operations */
E(`C o6S7V      long  ru_oublock;          /* block output operations */BSD爱好者乐园8p cb3G~,E vtFQ&?+m
      long  ru_msgsnd;           /* messages sent */BSD爱好者乐园Z"R.Xm(ZfmH
      long  ru_msgrcv;           /* messages received */BSD爱好者乐园h KR8_*v@
      long  ru_nsignals;         /* signals received */
v0?j5\1Tx      long  ru_nvcsw;            /* voluntary context switches */
9oy*R{"i _BU      long  ru_nivcsw;           /* involuntary " */BSD爱好者乐园@h(oA!v"I7A6V
  };

d2oy2jO%NY1|我们来详细分析每一个成员变量。
Y{:h*Fp6g,hj*aru_utime,ru_stime
1j;M5s|%Dru_utime和ru_stime成员变量包含了在用户模式和系统模式中执行时间的总和。它们都使用timeval结构(请查看前一章来了解此结构。)BSD爱好者乐园a)ae2_F&ty
BSD爱好者乐园^!p"I'p.M3J
ru_maxrssBSD爱好者乐园(_Pit ln3il g;} O
ru_maxrss保存了常驻集的内存使用数。其值根据内存分页的使用来确定。BSD爱好者乐园:srB\c

,K&ZP6YDru_ixrssBSD爱好者乐园AIzv_g
ru_ixrss值指文本段(text segment)使用的内存数乘以执行滴答数。BSD爱好者乐园t)uv2^/C[I_ @

1Wa;Bg8}0hru_idrss
3|g7L+}$NE}N Zru_idrss 值指进程所使用的私有内存数(KB)乘以执行滴答数来。BSD爱好者乐园^!U#s u8ii(A:d

Yy,T_ @`ru_isrssBSD爱好者乐园-g[ Jy&S6v
ru_isrss 指栈使用的内存数(KB为单位)乘以执行滴答数。BSD爱好者乐园l(jd'?1C A U$JY:G
BSD爱好者乐园-i GL)D4bT$j1p~
ru_minflt
3dO&r(VeuH8qk#Gru_minflt值指不需要I/O的页缺失数。页缺失发生在内核需要得到一个内存页以供进程访问时。
of1{N!si
Z t1YMopWTru_majfltBSD爱好者乐园9|r!U Nl!ww,~
ru_majflt值指需要I/O的页缺失数。页缺失发生在内核需要得到一个内存页以供进程访问时。BSD爱好者乐园 uZ3^_#frX

[9\0r$]zO ]uru_nswap
d^h1KyY有时,一个进程会被调出内存,以提供空间给其他进程使用。ru_nswap指的就是一个进程将要调出内存的次数。
%`,rt%Tz@'{BSD爱好者乐园;o*u.uf*Y!`.@
ru_inblock
&G8g0H.H9]ru_inblock 指文件系统需要为一个读请求执行输入操作的次数。
3M8x6T~$T6m
+m$G6@ry|?T8}ru_oublockBSD爱好者乐园}\Ql3ye3f(b
ru_oublock指文件系统需要为一个写入请求执行输出操作的次数。BSD爱好者乐园6W4[ acr/h zLe sW
BSD爱好者乐园p*G+o#A(Ko
ru_msgsnd
q!bdlA u/O"Jru_msgsnd指发送的IPC信息总数BSD爱好者乐园3W-HD)dx#Dh?x
BSD爱好者乐园$LR#|'y-~4q
ru_msgrcvBSD爱好者乐园']]3kFi T
ru_msgrcv指收到的IPC信息总数。BSD爱好者乐园ej2z-S jJ8t

,H+P GDSSA7\ru_nsignals
I$j(l_c?ru_nsignals指进程收到的信号总数。
f2xNX)pUV0to
Y&R,kdf] ~Gru_nvcswBSD爱好者乐园HX*`7@:g
一个进程主动上下文且混总数。主动上下文切换发生在一个进程放弃它的CPU分时时。通常发生在一个进程等待某可用资源时。
bO Uu'b"G8wy-{
?*[z'd&|/e4_5Fru_nivcswBSD爱好者乐园PI8n:xxB
ru_nivcsw包含了因高优先级进程运行导致的上下文切换总数。BSD爱好者乐园4T8nRHr3a\0f?
BSD爱好者乐园R*k7[5|Tl.~!~c
7.4 小结
;^sS0f @本章主要阐述了程序如何得到系统限制。这些限制不应该固定写入你的代码。取而代之的是,你的程序应该使用这些接口。这是因为这些限制是与平台相关的,甚至不同系统间都会有差别。比如,系统管理员可以调整允许打开的最大文件数,因此如果你需要增加或者减小这个值,就不能将值4096固定写入程序中。另一个例子是分页大小。一些64位系统使用8096作为默认的分页大小,但是大多数的32位系统将此默认值设置位4096。再次强调,这是个可调整的参数,不应该使用一个固定的值。
N)J.Uh#r8t:@我们还学习了一个程序如何得到其资源的当前使用量,或者查看其子进程的资源使用状况。使用这些接口可以帮助我们检测甚至避免出现失控的进程。它们用在程序试图超越其软/硬限制时调试错误也非常不错。因为使用范围的限制,BSD方面文章更新速度不快,站长会坚持每天更新博客,欢迎访问!
[版权声明]BSD爱好者乐园站内文章,如来源不是互联网,则均系原创或翻译之作,可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。
TAG: freebsd FreeBSD 系统编程
 

评分:0

我来说两句

seccode