【问题标题】:How does the kernel determine the next pid?内核如何确定下一个pid?
【发布时间】:2014-05-18 06:03:25
【问题描述】:

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

我找到了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. 为什么这段代码必须“尝试”一个 pid?这段代码很活泼吗?如果多个进程同时尝试获取 pid,会发生什么情况?
  5. 是否可以使用特定的 pid 启动进程?

【问题讨论】:

    标签: kernel freebsd


    【解决方案1】:

    为什么会有随机性?这真的增加了安全性吗?还是只是为了帮助制造碎片化?

    随机 PID 不会增加太多安全性。随机 PID 的意义在于使 PID 更有可能在被选择的空间中可用,以减少发生冲突的机会。

    为什么这段代码必须“尝试”一个 pid?这段代码很活泼吗?如果多个进程同时尝试获取 pid,会发生什么情况?

    仔细看,整个东西都有锁。 “尝试”部分是扫描僵尸列表和其他列表的时候。

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

    没有。

    【讨论】:

      猜你喜欢
      • 2011-03-27
      • 2018-07-02
      • 1970-01-01
      • 2016-05-25
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 2016-10-01
      相关资源
      最近更新 更多