内核如何确定下一个pid?

时间:2014-05-16 05:32:51

标签: kernel freebsd

我想了解FreeBSD内核如何分配pids?

我找到了following code

 186 static int randompid = 0;
 187 
 188 static int
 189 sysctl_kern_randompid(SYSCTL_HANDLER_ARGS)
 190 {
 191         int error, pid;
 192 
 193         error = sysctl_wire_old_buffer(req, sizeof(int));
 194         if (error != 0)
 195                 return(error);
 196         sx_xlock(&allproc_lock);
 197         pid = randompid;
 198         error = sysctl_handle_int(oidp, &pid, 0, req);
 199         if (error == 0 && req->newptr != NULL) {
 200                 if (pid < 0 || pid > pid_max - 100)     /* out of range */
 201                         pid = pid_max - 100;
 202                 else if (pid < 2)                       /* NOP */
 203                         pid = 0;
 204                 else if (pid < 100)                     /* Make it reasonable */
 205                         pid = 100;
 206                 randompid = pid;
 207         }
 208         sx_xunlock(&allproc_lock);
 209         return (error);
 210 }
 211 
 212 SYSCTL_PROC(_kern, OID_AUTO, randompid, CTLTYPE_INT|CTLFLAG_RW,
 213     0, 0, sysctl_kern_randompid, "I", "Random PID modulus");
 214 
 215 static int
 216 fork_findpid(int flags)
 217 {
 218         struct proc *p;
 219         int trypid;
 220         static int pidchecked = 0;
 221 
 222         /*
 223          * Requires allproc_lock in order to iterate over the list
 224          * of processes, and proctree_lock to access p_pgrp.
 225          */
 226         sx_assert(&allproc_lock, SX_LOCKED);
 227         sx_assert(&proctree_lock, SX_LOCKED);
 228 
 229         /*
 230          * Find an unused process ID.  We remember a range of unused IDs
 231          * ready to use (from lastpid+1 through pidchecked-1).
 232          *
 233          * If RFHIGHPID is set (used during system boot), do not allocate
 234          * low-numbered pids.
 235          */
 236         trypid = lastpid + 1;
 237         if (flags & RFHIGHPID) {
 238                 if (trypid < 10)
 239                         trypid = 10;
 240         } else {
 241                 if (randompid)
 242                         trypid += arc4random() % randompid;
 243         }
 244 retry:
 245         /*
 246          * If the process ID prototype has wrapped around,
 247          * restart somewhat above 0, as the low-numbered procs
 248          * tend to include daemons that don't exit.
 249          */
 250         if (trypid >= pid_max) {
 251                 trypid = trypid % pid_max;
 252                 if (trypid < 100)
 253                         trypid += 100;
 254                 pidchecked = 0;
 255         }
 256         if (trypid >= pidchecked) {
 257                 int doingzomb = 0;
 258 
 259                 pidchecked = PID_MAX;
 260                 /*
 261                  * Scan the active and zombie procs to check whether this pid
 262                  * is in use.  Remember the lowest pid that's greater
 263                  * than trypid, so we can avoid checking for a while.
 264                  */
 265                 p = LIST_FIRST(&allproc);
 266 again:
 267                 for (; p != NULL; p = LIST_NEXT(p, p_list)) {
 268                         while (p->p_pid == trypid ||
 269                             (p->p_pgrp != NULL &&
 270                             (p->p_pgrp->pg_id == trypid ||
 271                             (p->p_session != NULL &&
 272                             p->p_session->s_sid == trypid)))) {
 273                                 trypid++;
 274                                 if (trypid >= pidchecked)
 275                                         goto retry;
 276                         }
 277                         if (p->p_pid > trypid && pidchecked > p->p_pid)
 278                                 pidchecked = p->p_pid;
 279                         if (p->p_pgrp != NULL) {
 280                                 if (p->p_pgrp->pg_id > trypid &&
 281                                     pidchecked > p->p_pgrp->pg_id)
 282                                         pidchecked = p->p_pgrp->pg_id;
 283                                 if (p->p_session != NULL &&
 284                                     p->p_session->s_sid > trypid &&
 285                                     pidchecked > p->p_session->s_sid)
 286                                         pidchecked = p->p_session->s_sid;
 287                         }
 288                 }
 289                 if (!doingzomb) {
 290                         doingzomb = 1;
 291                         p = LIST_FIRST(&zombproc);
 292                         goto again;
 293                 }
 294   
 296         /*
 297          * RFHIGHPID does not mess with the lastpid counter during boot.
 298          */
 299         if (flags & RFHIGHPID)
 300                 pidchecked = 0;
 301         else
 302                 lastpid = trypid;
 303 
 304         return (trypid);
 305 }
 306 

但我有一些问题:

  1. RFHIGHPID用于什么?
  2. 为什么会出现随机性?这实际上增加了安全性吗?或者这只是为了帮助创建碎片?
  3. randompid在哪里设置?
  4. 为什么此代码必须尝试&#39;一个pid?这段代码有点活泼吗?如果多个进程同时尝试获取pid会发生什么?
  5. 是否可以使用特定的pid启动进程?

1 个答案:

答案 0 :(得分:1)

  

为什么会出现随机性?这实际上增加了安全性吗?或者这只是为了帮助创建碎片?

随机PID不会增加太多安全性。随机PID的重点是使PID更有可能在空间中可用,以减少冲突的可能性。

  

为什么此代码必须尝试&#39;一个pid?这段代码有点活泼吗?如果多个进程同时尝试获取pid会发生什么?

仔细观察,整个事物都有锁定。 &#39;尝试&#39;部分是它扫描僵尸列表和其他列表。

  

是否可以使用特定的pid启动进程?

没有