ulimit について

リソースの制限値は、まず /etc/login.conf により設定される。
ulimit は B系シェルの組み込みコマンド。C系シェルでは limit, unlimit を使う。
FreeBSD には /usr/bin/limits というコマンドもある。
ソフトリミット=一般ユーザが変更できる
ハードリミット=一般ユーザは上げることができない。下げることはできる。
ulimit の -S/-H オプションを指定しないとハード・ソフト両方変更される。
sshLinux に接続した場合、

bash: ulimit: cannot modify limit: Operation not permitted

というエラーが出るという FAQ がある。
これは ssh 経由で接続したプロセスに対し、/etc/security/limits.conf の設定が反映されないため。
sshd_config で特権分離をオフにすれば /etc/security/limits.conf が読まれるようになる。

UsePrivilegeSeparation no

http://www.miraclelinux.com/technet/faq/data/00073.html


特権分離について
http://www.citi.umich.edu/u/provos/ssh/privsep-j.html


ulimit のソースはこんな感じ。
max user proc 取得。

long
getmaxchild ()
{
  static long maxchild = -1L;

  if (maxchild > 0)
    return maxchild;

#if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
  maxchild = sysconf (_SC_CHILD_MAX);
#else
#  if defined (CHILD_MAX)
  maxchild = CHILD_MAX;
#  else
#    if defined (MAXUPRC)
  maxchild = MAXUPRC;
#    endif /* MAXUPRC */
#  endif /* CHILD_MAX */
#endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */

  return (maxchild);
}

set。ulimit(3) を使ったり setrlimit(2) を使ったり、いろいろ。

static int
set_limit (ind, newlim, mode)
     int ind;
     RLIMTYPE newlim;
     int mode;
{
#if defined (HAVE_RESOURCE)
   struct rlimit limit;
   RLIMTYPE val;
#endif

  if (limits[ind].parameter >= 256)
    switch (limits[ind].parameter)
      {
      case RLIMIT_FILESIZE:
#if !defined (HAVE_RESOURCE)
	return (ulimit (2, newlim / 512L));
#else
	errno = EINVAL;
	return -1;
#endif

      case RLIMIT_OPENFILES:
#if defined (HAVE_SETDTABLESIZE)
#  if defined (__CYGWIN__)
	/* Grrr... Cygwin declares setdtablesize as void. */
	setdtablesize (newlim);
	return 0;
#  else
	return (setdtablesize (newlim));
#  endif
#endif
      case RLIMIT_PIPESIZE:
      case RLIMIT_VIRTMEM:
      case RLIMIT_MAXUPROC:
      default:
	errno = EINVAL;
	return -1;
      }
  else
    {
#if defined (HAVE_RESOURCE)
      if (getrlimit (limits[ind].parameter, &limit) < 0)
	return -1;
#  if defined (HPUX9)
      if (limits[ind].parameter == RLIMIT_FILESIZE)
	newlim /= 512;				/* Ugh. */
#  endif /* HPUX9 */
      val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
	       (mode & LIMIT_HARD) == 0 &&		/* XXX -- test */
	       (limit.rlim_cur <= limit.rlim_max))
		 ? limit.rlim_max : newlim;
      if (mode & LIMIT_SOFT)
	limit.rlim_cur = val;
      if (mode & LIMIT_HARD)
	limit.rlim_max = val;
	  
      return (setrlimit (limits[ind].parameter, &limit));
#else
      errno = EINVAL;
      return -1;
#endif
    }
} 

非常に素朴な疑問なのだが、なぜ ulimit はシェル組み込みコマンドなのだろう?


ulimitについて(2)
http://d.hatena.ne.jp/parasporospa/20070414

bash の ulimit と getrlimit のシンボルの対応

static RESOURCE_LIMITS limits[] = {
#ifdef RLIMIT_PTHREAD
  { 'T',	RLIMIT_PTHREAD,  1,	"number of threads",	(char *)NULL },
#endif
#ifdef RLIMIT_SBSIZE
  { 'b',	RLIMIT_SBSIZE,  1,	"socket buffer size",	"bytes" },
#endif
#ifdef RLIMIT_CORE
  { 'c',	RLIMIT_CORE,  POSIXBLK,	"core file size",	"blocks" },
#endif
#ifdef RLIMIT_DATA
  { 'd',	RLIMIT_DATA,  1024,	"data seg size",	"kbytes" },
#endif
#ifdef RLIMIT_NICE
  { 'e',	RLIMIT_NICE,  1,	"scheduling priority",	(char *)NULL },
#endif
  { 'f',	RLIMIT_FILESIZE, POSIXBLK,	"file size",		"blocks" },
#ifdef RLIMIT_SIGPENDING
  { 'i',	RLIMIT_SIGPENDING, 1,	"pending signals",	(char *)NULL },
#endif
#ifdef RLIMIT_MEMLOCK
  { 'l',	RLIMIT_MEMLOCK, 1024,	"max locked memory",	"kbytes" },
#endif
#ifdef RLIMIT_RSS
  { 'm',	RLIMIT_RSS,   1024,	"max memory size",	"kbytes" },
#endif /* RLIMIT_RSS */
  { 'n',	RLIMIT_OPENFILES, 1,	"open files",		(char *)NULL},
  { 'p',	RLIMIT_PIPESIZE, 512,	"pipe size", 		"512 bytes" },
#ifdef RLIMIT_MSGQUEUE
  { 'q',	RLIMIT_MSGQUEUE, 1,	"POSIX message queues",	"bytes" },
#endif
#ifdef RLIMIT_RTPRIO
  { 'r',	RLIMIT_RTPRIO,  1,	"real-time priority",	(char *)NULL },
#endif
#ifdef RLIMIT_STACK
  { 's',	RLIMIT_STACK, 1024,	"stack size",		"kbytes" },
#endif
#ifdef RLIMIT_CPU
  { 't',	RLIMIT_CPU,      1,	"cpu time",		"seconds" },
#endif /* RLIMIT_CPU */
  { 'u',	RLIMIT_MAXUPROC, 1,	"max user processes",	(char *)NULL },
#if defined (HAVE_RESOURCE)
  { 'v',	RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory", "kbytes" },
#endif
#ifdef RLIMIT_SWAP
  { 'w',	RLIMIT_SWAP,	1024,	"swap size",		"kbytes" },
#endif
#ifdef RLIMIT_LOCKS
  { 'x',	RLIMIT_LOCKS,	1,	"file locks",		(char *)NULL },
#endif
  { -1, -1, -1, (char *)NULL, (char *)NULL }
};
#if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
#  define RLIMIT_NOFILE RLIMIT_OFILE
#endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */

/* Some systems have these, some do not. */
#ifdef RLIMIT_FSIZE
#  define RLIMIT_FILESIZE	RLIMIT_FSIZE
#else
#  define RLIMIT_FILESIZE	256
#endif

#define RLIMIT_PIPESIZE	257

#ifdef RLIMIT_NOFILE
#  define RLIMIT_OPENFILES	RLIMIT_NOFILE
#else
#  define RLIMIT_OPENFILES	258
#endif

#ifdef RLIMIT_VMEM
#  define RLIMIT_VIRTMEM	RLIMIT_VMEM
#  define RLIMIT_VMBLKSZ	1024
#else
#  ifdef RLIMIT_AS
#    define RLIMIT_VIRTMEM	RLIMIT_AS
#    define RLIMIT_VMBLKSZ	1024
#  else
#    define RLIMIT_VIRTMEM	259
#    define RLIMIT_VMBLKSZ	1
#  endif
#endif

#ifdef RLIMIT_NPROC
#  define RLIMIT_MAXUPROC	RLIMIT_NPROC
#else
#  define RLIMIT_MAXUPROC	260
#endif

#if !defined (RLIM_INFINITY)
#  define RLIM_INFINITY 0x7fffffff
#endif

#if !defined (RLIM_SAVED_CUR)
#  define RLIM_SAVED_CUR RLIM_INFINITY
#endif

#if !defined (RLIM_SAVED_MAX)
#  define RLIM_SAVED_MAX RLIM_INFINITY
#endif