?? exec.c
字號:
17328 if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC);
17329
17330 *ft = ( (hdr.a_flags & A_SEP) ? SEPARATE : 0); /* separate I & D or not */
17331
17332 /* Get text and data sizes. */
17333 *text_bytes = (vir_bytes) hdr.a_text; /* text size in bytes */
17334 *data_bytes = (vir_bytes) hdr.a_data; /* data size in bytes */
17335 *bss_bytes = (vir_bytes) hdr.a_bss; /* bss size in bytes */
17336 *tot_bytes = hdr.a_total; /* total bytes to allocate for prog */
17337 *sym_bytes = hdr.a_syms; /* symbol table size in bytes */
17338 if (*tot_bytes == 0) return(ENOEXEC);
17339
17340 if (*ft != SEPARATE) {
17341
17342 /* If I & D space is not separated, it is all considered data. Text=0*/
17343 *data_bytes += *text_bytes;
17344 *text_bytes = 0;
17345
17346 }
17347 *pc = hdr.a_entry; /* initial address to start execution */
17348
17349 /* Check to see if segment sizes are feasible. */
17350 tc = ((unsigned long) *text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
17351 dc = (*data_bytes + *bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
17352 totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
17353 if (dc >= totc) return(ENOEXEC); /* stack must be at least 1 click */
17354 dvir = (*ft == SEPARATE ? 0 : tc);
17355 s_vir = dvir + (totc - sc);
17356 m = size_ok(*ft, tc, dc, sc, dvir, s_vir);
17357 ct = hdr.a_hdrlen & BYTE; /* header length */
17358 if (ct > A_MINHDR) lseek(fd, (off_t) ct, SEEK_SET); /* skip unused hdr */
17359 return(m);
17360 }
17363 /*===========================================================================*
17364 * new_mem *
17365 *===========================================================================*/
17366 PRIVATE int new_mem(sh_mp, text_bytes, data_bytes,bss_bytes,stk_bytes,tot_bytes)
17367 struct mproc *sh_mp; /* text can be shared with this process */
17368 vir_bytes text_bytes; /* text segment size in bytes */
17369 vir_bytes data_bytes; /* size of initialized data in bytes */
17370 vir_bytes bss_bytes; /* size of bss in bytes */
17371 vir_bytes stk_bytes; /* size of initial stack segment in bytes */
17372 phys_bytes tot_bytes; /* total memory to allocate, including gap */
17373 {
17374 /* Allocate new memory and release the old memory. Change the map and report
17375 * the new map to the kernel. Zero the new core image's bss, gap and stack.
17376 */
17377
17378 register struct mproc *rmp;
17379 vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
17380 phys_clicks new_base;
17381
17382 static char zero[1024]; /* used to zero bss */
17383 phys_bytes bytes, base, count, bss_offset;
17384
17385 /* No need to allocate text if it can be shared. */
17386 if (sh_mp != NULL) text_bytes = 0;
17387
17388 /* Acquire the new memory. Each of the 4 parts: text, (data+bss), gap,
17389 * and stack occupies an integral number of clicks, starting at click
17390 * boundary. The data and bss parts are run together with no space.
17391 */
17392
17393 text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
17394 data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
17395 stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
17396 tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
17397 gap_clicks = tot_clicks - data_clicks - stack_clicks;
17398 if ( (int) gap_clicks < 0) return(ENOMEM);
17399
17400 /* Check to see if there is a hole big enough. If so, we can risk first
17401 * releasing the old core image before allocating the new one, since we
17402 * know it will succeed. If there is not enough, return failure.
17403 */
17404 if (text_clicks + tot_clicks > max_hole()) return(EAGAIN);
17405
17406 /* There is enough memory for the new core image. Release the old one. */
17407 rmp = mp;
17408
17409 if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
17410 /* No other process shares the text segment, so free it. */
17411 free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
17412 }
17413 /* Free the data and stack segments. */
17414 free_mem(rmp->mp_seg[D].mem_phys,
17415 rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir); //???-
17416
17417 /* We have now passed the point of no return. The old core image has been
17418 * forever lost. The call must go through now. Set up and report new map.
17419 */
17420 new_base = alloc_mem(text_clicks + tot_clicks); /* new core image */
17421 if (new_base == NO_MEM) panic("MM hole list is inconsistent", NO_NUM);
17422
17423 if (sh_mp != NULL) {
17424 /* Share the text segment. */
17425 rmp->mp_seg[T] = sh_mp->mp_seg[T];
17426 } else {
17427 rmp->mp_seg[T].mem_phys = new_base;
17428 rmp->mp_seg[T].mem_vir = 0;
17429 rmp->mp_seg[T].mem_len = text_clicks;
17430 }
17431 rmp->mp_seg[D].mem_phys = new_base + text_clicks;
17432 rmp->mp_seg[D].mem_vir = 0;
17433 rmp->mp_seg[D].mem_len = data_clicks;
17434 rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
17435 rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
17436 rmp->mp_seg[S].mem_len = stack_clicks;
17437
17438
17439 sys_newmap(who, rmp->mp_seg); /* report new map to the kernel */
17440
17441 /* Zero the bss, gap, and stack segment. */
17442 bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
17443 base = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
17444 bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;
17445 base += bss_offset;
17446 bytes -= bss_offset;
17447
17448 while (bytes > 0) {
17449 count = MIN(bytes, (phys_bytes) sizeof(zero));
17450 if (sys_copy(MM_PROC_NR, D, (phys_bytes) zero,
17451 ABS, 0, base, count) != OK) {
17452 panic("new_mem can't zero", NO_NUM);
17453 }
17454 base += count;
17455 bytes -= count;
17456 }
17457
17458 return(OK);
17459 }
17462 /*===========================================================================*
17463 * patch_ptr *
17464 *===========================================================================*/
17465 PRIVATE void patch_ptr(stack, base)
17466 char stack[ARG_MAX]; /* pointer to stack image within MM */
17467 vir_bytes base; /* virtual address of stack base inside user */
17468 {
17469 /* When doing an exec(name, argv, envp) call, the user builds up a stack
17470 * image with arg and env pointers relative to the start of the stack. Now
17471 * these pointers must be relocated, since the stack is not positioned at
17472 * address 0 in the user's address space.
17473 */
17474
17475 char **ap, flag;
17476 vir_bytes v;
17477
17478 flag = 0; /* counts number of 0-pointers seen */
17479 ap = (char **) stack; /* points initially to 'nargs' */
17480 ap++; /* now points to argv[0] */
17481 while (flag < 2) {
17482 if (ap >= (char **) &stack[ARG_MAX]) return; /* too bad */
17483 if (*ap != NIL_PTR) {
17484 v = (vir_bytes) *ap; /* v is relative pointer */
17485 v += base; /* relocate it */
17486 *ap = (char *) v; /* put it back */
17487 } else {
17488 flag++;
17489 }
17490 ap++;
17491 }
17492 }
17495 /*===========================================================================*
17496 * load_seg *
17497 *===========================================================================*/
17498 PRIVATE void load_seg(fd, seg, seg_bytes)
17499 int fd; /* file descriptor to read from */
17500 int seg; /* T or D */
17501 vir_bytes seg_bytes; /* how big is the segment */
17502 {
17503 /* Read in text or data from the exec file and copy to the new core image.
17504 * This procedure is a little bit tricky. The logical way to load a segment
17505 * would be to read it block by block and copy each block to the user space
17506 * one at a time. This is too slow, so we do something dirty here, namely
17507 * send the user space and virtual address to the file system in the upper
17508 * 10 bits of the file descriptor, and pass it the user virtual address
17509 * instead of a MM address. The file system extracts these parameters when
17510 * gets a read call from the memory manager, which is the only process that
17511 * is permitted to use this trick. The file system then copies the whole
17512 * segment directly to user space, bypassing MM completely.
17513 */
17514
17515 int new_fd, bytes;
17516 char *ubuf_ptr;
17517
17518 new_fd = (who << 8) | (seg << 6) | fd;
17519 ubuf_ptr = (char *) ((vir_bytes)mp->mp_seg[seg].mem_vir << CLICK_SHIFT);
17520 while (seg_bytes != 0) {
17521 bytes = (INT_MAX / BLOCK_SIZE) * BLOCK_SIZE;
17522 if (seg_bytes < bytes)
17523 bytes = (int)seg_bytes;
17524 if (read(new_fd, ubuf_ptr, bytes) != bytes)
17525 break; /* error */
17526 ubuf_ptr += bytes;
17527 seg_bytes -= bytes;
17528 }
17529 }
17532 /*===========================================================================*
17533 * find_share *
17534 *===========================================================================*/
17535 PUBLIC struct mproc *find_share(mp_ign, ino, dev, ctime)
17536 struct mproc *mp_ign; /* process that should not be looked at */
17537 ino_t ino; /* parameters that uniquely identify a file */
17538 dev_t dev;
17539 time_t ctime;
17540 {
17541 /* Look for a process that is the file <ino, dev, ctime> in execution. Don't
17542 * accidentally "find" mp_ign, because it is the process on whose behalf this
17543 * call is made.
17544 */
17545 struct mproc *sh_mp;
17546
17547 for (sh_mp = &mproc[INIT_PROC_NR]; sh_mp < &mproc[NR_PROCS]; sh_mp++) {
17548 if ((sh_mp->mp_flags & (IN_USE | HANGING | SEPARATE))
17549 != (IN_USE | SEPARATE)) continue;
17550 if (sh_mp == mp_ign) continue;
17551 if (sh_mp->mp_ino != ino) continue;
17552 if (sh_mp->mp_dev != dev) continue;
17553 if (sh_mp->mp_ctime != ctime) continue;
17554 return sh_mp;
17555 }
17556 return(NULL);
17557 }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -