fd/pid选择及fd/signal数量限制
一、资源
这些是一个系统级的行为特征,并且可能没啥直接关系,只是比较琐碎,所以放在一起做个总结,以后查询也方便一些。
二、fd/pid回收问题
这两个是系统中一个重要的handle,区别在于fd是进程内相关,而pid是系统级(据说加入namespace之后系统也可以有相同pid的进程),这些大家都知道,所以不是本文讨论的重点。这里想说的是他们的选择,就是这些值如何选择,这个问题引申的一个有意义的问题就是他们是否会回绕,例如,一个id被释放了,它是否会马上就被下一个申请者复用?这在系统级编程的时候还是一个值得关注的问题。假设我们知道一个pid(先不管如何得到的,例如fork的子进程或者通过管道接收的),然后把它保存起来,过了一段时间,我们希望终止掉这个线程,就给它发一个信号,但是如果说在这个过程中这个pid对应的原始任务已经退出,并且这个pid已经分配给另一个任务,那么此时就可能会出现误杀情况。
对于fd同样存在这种问题,过一段时间关闭的fd可能是另一个新的fd,而原始的fd已经关闭。
事实上,fd的回收是实时的,假设说一个fd被释放,那么下次打开的时候就可能会分到这个刚释放的fd,它每次都是从0开始搜索第一个没有被使用的fd,所以延迟的不小心关闭可能的确会产生关闭其他人文件的显现。
但是对于pid,谢天谢地,它的回收没有这么快,它是从当前系统中已经被用过的最大的pid(不论这个pid对应的任务是否已经关闭)之后开始的。
三、fd/signal数量限制
int get_unused_fd(void)
/*
* N.B. For clone tasks sharing a files structure, this test
* will limit the total number of files that can be opened.
*/
if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
goto out;
在linux-2.6.21\include\asm-generic\resource.h
[RLIMIT_NOFILE] = { INR_OPEN, INR_OPEN }, \
#define INR_OPEN 1024 /* Initial setting for nfile rlimits */
即一个进程最多可以打开1024个文件,当然可以通过系统调用修改这个限制。
signal的限制
static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
int override_rlimit)
if (override_rlimit ||
atomic_read(&user->sigpending) <=
t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, flags);
这里限制pending信号的数量不能太多,如果太多那么消息丢失,但是现在的问题是这个太多是多大范围内。通过代码看到,这个范围是系统中这个用户所创建的所有的进程中pending的信号总数。关于这一点,可以在系统中通过
[root@Harry ~]# cat /proc/30052/status
Name: su
State: S (sleeping)
Tgid: 30052
Pid: 30052
PPid: 4969
TracerPid: 0
Uid: 500 0 0 0
Gid: 500 500 500 500
Utrace: 0
FDSize: 256
Groups: 500
VmPeak: 7996 kB
VmSize: 7532 kB
VmLck: 0 kB
VmHWM: 3252 kB
VmRSS: 2964 kB
VmData: 936 kB
VmStk: 84 kB
VmExe: 28 kB
VmLib: 4220 kB
VmPTE: 56 kB
Threads: 1
SigQ: 4/8192
SigPnd: 0000000000000000
ShdPnd: 0002000000000001
SigBlk: fffffffe7ffb9eff
SigIgn: 0000000000001000
SigCgt: 0000000180004000
CapInh: 0000000000000000
CapPrm: ffffffffffffffff
CapEff: ffffffffffffffff
CapBnd: ffffffffffffffff
Cpus_allowed: 1
Cpus_allowed_list: 0
Mems_allowed: 1
Mems_allowed_list: 0
voluntary_ctxt_switches: 8
nonvoluntary_ctxt_switches: 52
[root@Harry ~]# kill -50 30052 发送一个被屏蔽的信号之后,用户累计信号加一,但是另一用户的该值并不会变化。
[root@Harry ~]# cat /proc/30052/status
Name: su
State: S (sleeping)
Tgid: 30052
Pid: 30052
PPid: 4969
TracerPid: 0
Uid: 500 0 0 0
Gid: 500 500 500 500
Utrace: 0
FDSize: 256
Groups: 500
VmPeak: 7996 kB
VmSize: 7532 kB
VmLck: 0 kB
VmHWM: 3252 kB
VmRSS: 2964 kB
VmData: 936 kB
VmStk: 84 kB
VmExe: 28 kB
VmLib: 4220 kB
VmPTE: 56 kB
Threads: 1
SigQ: 5/8192
SigPnd: 0000000000000000
ShdPnd: 0002000000000001
SigBlk: fffffffe7ffb9eff
SigIgn: 0000000000001000
SigCgt: 0000000180004000
CapInh: 0000000000000000
CapPrm: ffffffffffffffff
CapEff: ffffffffffffffff
CapBnd: ffffffffffffffff
Cpus_allowed: 1
Cpus_allowed_list: 0
Mems_allowed: 1
Mems_allowed_list: 0
voluntary_ctxt_switches: 8
nonvoluntary_ctxt_switches: 52
[root@Harry ~]# cat /proc/1/status
Name: init
State: S (sleeping)
Tgid: 1
Pid: 1
PPid: 0
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
Utrace: 0
FDSize: 32
Groups:
VmPeak: 2136 kB
VmSize: 2044 kB
VmLck: 0 kB
VmHWM: 836 kB
VmRSS: 704 kB
VmData: 196 kB
VmStk: 84 kB
VmExe: 132 kB
VmLib: 1600 kB
VmPTE: 28 kB
Threads: 1
SigQ: 3/8192
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 00000000280b6423
CapInh: 0000000000000000
CapPrm: ffffffffffffffff
CapEff: fffffffffffffeff
CapBnd: ffffffffffffffff
Cpus_allowed: 1
Cpus_allowed_list: 0
Mems_allowed: 1
Mems_allowed_list: 0
voluntary_ctxt_switches: 478
nonvoluntary_ctxt_switches: 174
[root@Harry ~]#