Kernel 内核如何确定下一个pid?

Kernel 内核如何确定下一个pid?,kernel,freebsd,Kernel,Freebsd,我试图理解FreeBSD内核如何分配PID 我发现: 186静态int-randompid=0; 187 188静态整数 189 sysctl\u kern\u randompid(sysctl\u HANDLER\u ARGS) 190 { 191整数误差,pid; 192 193错误=sysctl_wire_old_缓冲区(req,sizeof(int)); 194如果(错误!=0) 195返回(错误); 196 sx锁和allproc锁; 197 pid=随机pid; 198错误=sysc

我试图理解FreeBSD内核如何分配PID

我发现:

186静态int-randompid=0;
187
188静态整数
189 sysctl\u kern\u randompid(sysctl\u HANDLER\u ARGS)
190 {
191整数误差,pid;
192
193错误=sysctl_wire_old_缓冲区(req,sizeof(int));
194如果(错误!=0)
195返回(错误);
196 sx锁和allproc锁;
197 pid=随机pid;
198错误=sysctl\u handle\u int(oidp和pid,0,req);
199如果(错误==0&&req->newptr!=NULL){
200如果(pid<0 | | pid>pid_max-100)/*超出范围*/
201 pid=pid_最大值-100;
202如果(pid<2)/*NOP*/
203 pid=0;
204否则,如果(pid<100)/*使其合理*/
205 pid=100;
206随机pid=pid;
207         }
208 sx_xunlock(和allproc_lock);
209返回(错误);
210 }
211
212 SYSCTL_PROC(_kern,OID_AUTO,randompid,CTLTYPE_INT | ctlfag_RW,
213 0,0,sysctl_kern_randompid,“I”,“随机PID模”);
214
215静态整数
216 fork_findpid(int标志)
217 {
218结构程序*p;
219-胰蛋白酶;
220静态整数=0;
221
222         /*
223*需要allproc_锁才能遍历列表
224*个进程,并使用proctree_锁访问p_pgrp。
225          */
226 sx_断言(&allproc_lock,sx_lock);
227 sx_断言(&proctree_lock,sx_lock);
228
229         /*
230*查找未使用的进程ID。我们记住一系列未使用的ID
231*随时可用(从上次PID+1到PID-1)。
232          *
233*如果设置了RFHIGHPID(在系统引导期间使用),则不分配
234*低编号PID。
235          */
236 trypid=lastpid+1;
237如果(标志和RFHIGHPID){
238如果(胰蛋白酶<10)
239胰蛋白酶=10;
240}其他{
241如果(随机PID)
242 trypid+=arc4random()%randompid;
243         }
244重试:
245         /*
246*如果流程ID原型已缠绕,
247*重新启动略高于0,因为编号较低的程序
248*倾向于包括不退出的守护进程。
249          */
250如果(trypid>=pid_max){
251 trypid=trypid%pid_max;
252如果(胰蛋白酶<100)
253胰蛋白酶+=100;
254=0;
255         }
256如果(trypid>=pidchecked){
257 int doingzomb=0;
258
259 PID检查=PID_最大值;
260                 /*
261*扫描活动和僵尸程序以检查此pid
262*正在使用中。记住最低pid值更大
263*比trypid高,所以我们可以暂时避免检查。
264                  */
265 p=列表_优先(&allproc);
266再次:
267 for(;p!=NULL;p=LIST_NEXT(p,p_LIST)){
268而(p->p_pid==trypid||
269(p->p_pgrp!=NULL&&
270(p->p_pgrp->p_id==trypid||
271(p->p_会话!=空&&
272 p->p_session->s_sid==trypid){
273胰蛋白酶++;
274如果(trypid>=pidchecked)
275转去重试;
276                         }
277如果(p->p_-pid>trypid&&pidchecked>p->p_-pid)
278 pidchecked=p->p_pid;
279如果(p->p_pgrp!=NULL){
280如果(p->p_pgrp->p_id>trypid&&
281(检查>p->p_pgrp->p_id)
282 pidchecked=p->p_pgrp->pg_id;
283如果(p->p_会话!=空&&
284 p->p_会话->s_sid>trypid&&
285 pidchecked>p->p_session->s_sid)
286 pidchecked=p->p_session->s_sid;
287                         }
288                 }
289如果(!doingzomb){
290 doingzomb=1;
291 p=列表第一(&zombproc);
292又去了;
293                 }
294
296         /*
297*RFHIGHPID在引导期间不会与lastpid计数器发生冲突。
298          */
299如果(标志和RFHIGHPID)
300=0;
301其他
302 lastpid=trypid;
303
304返回(trypid);
305 }
306
但我有几个问题:

  • RFHIGHPID用于什么
  • 为什么会有随机性?这实际上增加了安全性吗?或者这只是为了帮助创建碎片
  • 在哪里设置了随机PID
  • 为什么此代码必须“尝试”pid?此代码是否快速?如果多个进程同时尝试获取pid会发生什么情况
  • 是否可以使用特定的pid启动流程
  • 为什么会有随机性?这实际上增加了安全性吗?或者这只是为了帮助创建碎片

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

    为什么此代码必须“尝试”pid?此代码是否快速?如果多个进程同时尝试获取pid会发生什么情况

    仔细看,整个东西周围都有一把锁。“试”部分是什么
     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