⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exec.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 2 页
字号:
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 + -