Thursday, December 22, 2011

[C] Resource Limit in Linux

之前开会大师兄问了下 'ulimit' 在底层用什么搞的,今天刚好遇到,就顺便写下来了。

内部有个“sys/resource.h”的库,里面主要有3个重要功能:
1. rlimit
2. rusage
3. priority

rlimit 挺好理解。rusage 跟 priority 不太懂,跟系统底层有关:一个是相关信息,一个是调度的优先级。

下面直接贴代码:
/*
 * =====================================================================================
 *
 *       Filename:  rlimit.c
 *
 *    Description:  Resources limit test
 *
 *        Version:  1.0
 *        Created:  Thursday, December 22, 2011 07:20:02 HKT
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Hongchao Deng (fengjingchao), fengjingchao@gmail.com
 *        Company:  Sun Yat-sen University
 *
 * =====================================================================================
 */




#include    <errno.h>
#include    <math.h> 
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>


#include <sys/types.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>




/*
 * ===  FUNCTION  ======================================================================
 *         Name:  work
 *  Description:  This function writes a string to a temporary file 10,000 times and then
 *                performs some arithmetic to generate load on CPU. HOW BAD...
 * =====================================================================================
 */
void
work (  )
{
   FILE *f;
   int i;
   double x = 4.5;


   f = tmpfile();


   // Writing about 10K to the tmp file
   for (i = 0; i < 10000; i++) {
      /* code */
      fprintf(f, "Do some output.\n");
      if( ferror(f) )
      {
         fprintf(stderr,"Error while writing to temporary file.\n");
         exit(EXIT_FAILURE);
      }
   }
  
   for (i = 0; i < 1000000; i++) {
      /* code */
      x = log(x*x+3.21);
   }


}        /* -----  end of function work  ----- */




/*
 * ===  FUNCTION  ======================================================================
 *         Name:  rusage_test
 *  Description: 
 * =====================================================================================
 */
void
rusage_test ( )
{
   struct rusage r_usage;
   work();
   getrusage(RUSAGE_SELF, &r_usage);
  
   printf("\n**************************************\n");


   printf ( "rusage information:\n" );
   printf ( "  ru_utime:\n    tv_sec.tv_usec: %ld.%06ld (s)\n",
                    r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec );
   printf ( "  ru_stime:\n    tv_sec.tv_usec: %ld.%06ld (s)\n",
                    r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec );

}        /* -----  end of function rusage_test  ----- */


/*
 * ===  FUNCTION  ======================================================================
 *         Name:  main
 *  Description:  main function
 * =====================================================================================
 */
    int
main ( int argc, char *argv[] )
{
   // parameters
   struct rlimit r_limit;


   // todo
   rusage_test();
   rusage_test();
   rusage_test();


   printf("\n**************************************\n"); 
   printf("priority information:\n");
   printf("  process priority: %d\n", getpriority(PRIO_PROCESS,getpid()));
   printf("  group   priority: %d\n", getpriority(PRIO_PGRP,getgid()));
   printf("  user    priority: %d\n", getpriority(PRIO_PGRP,getuid()));


   printf("\n**************************************\n"); 
   printf("rlimit information: (RLIM_INFINITY=%ld)\n", RLIM_INFINITY);


   getrlimit(RLIMIT_CPU, &r_limit);
   printf ( "  rlimit_cpu:\n    s: %ld ; h: %ld\n", r_limit.rlim_cur, r_limit.rlim_max );


   getrlimit(RLIMIT_DATA, &r_limit);
   printf ( "  rlimit_data:\n    s: %ld ; h: %ld\n", r_limit.rlim_cur, r_limit.rlim_max );


   getrlimit(RLIMIT_FSIZE, &r_limit);
   printf ( "  rlimit_fsize:\n    s: %ld ; h: %ld\n", r_limit.rlim_cur, r_limit.rlim_max );


   getrlimit(RLIMIT_NOFILE, &r_limit);
   printf ( "  rlimit_nofile:\n    s: %ld ; h: %ld\n", r_limit.rlim_cur, r_limit.rlim_max );


   getrlimit(RLIMIT_NPROC, &r_limit);
   printf ( "  rlimit_nproc:\n    s: %ld ; h: %ld\n", r_limit.rlim_cur, r_limit.rlim_max );


   printf("\nNow try to set some limits:\n");
   r_limit.rlim_cur = 1024; r_limit.rlim_max = RLIM_INFINITY;
   setrlimit(RLIMIT_FSIZE, &r_limit);
   work();


    return EXIT_SUCCESS;
}        /* ----------  end of function main  ---------- */


输出样例:
**************************************
rusage information:
  ru_utime:
    tv_sec.tv_usec: 0.040002 (s)
  ru_stime:
    tv_sec.tv_usec: 0.000000 (s)

**************************************
rusage information:
  ru_utime:
    tv_sec.tv_usec: 0.084005 (s)
  ru_stime:
    tv_sec.tv_usec: 0.000000 (s)

**************************************
rusage information:
  ru_utime:
    tv_sec.tv_usec: 0.128008 (s)
  ru_stime:
    tv_sec.tv_usec: 0.000000 (s)

**************************************
priority information:
  process priority: 0
  group   priority: -1
  user    priority: -1

**************************************
rlimit information: (RLIM_INFINITY=-1)
  rlimit_cpu:
    s: -1 ; h: -1
  rlimit_data:
    s: -1 ; h: -1
  rlimit_fsize:
    s: -1 ; h: -1
  rlimit_nofile:
    s: 1024 ; h: 4096
  rlimit_nproc:
    s: 15915 ; h: 15915

Now try to set some limits:
File size limit exceeded



感悟:
1. 调用getrusage的时候,只是得到当前耗掉的时间,这点在上面我用了几次work中体现出来了。
2. priority是数值越小,优先越高。
3. 普通人set的时候只能变弱,即priority+,limit - 。superuser有能力set,但是在内核限制的范围内。
4. 为什么要有soft & hard limit 两种呢?查了下,是因为soft 是能提高的,但是hard普通用户只能减少,这样有个限度。

References:
http://linux.about.com/library/cmd/blcmdl2_setrlimit.htm
http://linux.die.net/man/2/getrusage
http://linux.die.net/man/2/gettimeofday
http://linux.die.net/man/2/setpriority
http://linux.die.net/man/2/nice

No comments:

Post a Comment