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

📄 exec.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Allocate new memory and release the old memory.  Change the map and report * the new map to the kernel.  Zero the new core image's bss, gap and stack. */  register struct mproc *rmp = mp;  vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;  phys_clicks new_base;  phys_bytes bytes, base, bss_offset;  int s;  /* No need to allocate text if it can be shared. */  if (sh_mp != NULL) text_bytes = 0;  /* Allow the old data to be swapped out to make room.  (Which is really a   * waste of time, because we are going to throw it away anyway.)   */  rmp->mp_flags |= WAITING;  /* Acquire the new memory.  Each of the 4 parts: text, (data+bss), gap,   * and stack occupies an integral number of clicks, starting at click   * boundary.  The data and bss parts are run together with no space.   */  text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;  data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;  stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;  tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;  gap_clicks = tot_clicks - data_clicks - stack_clicks;  if ( (int) gap_clicks < 0) return(ENOMEM);  /* Try to allocate memory for the new process. */  new_base = alloc_mem(text_clicks + tot_clicks);  if (new_base == NO_MEM) return(ENOMEM);  /* We've got memory for the new core image.  Release the old one. */  rmp = mp;  if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {	/* No other process shares the text segment, so free it. */	free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);  }  /* Free the data and stack segments. */  free_mem(rmp->mp_seg[D].mem_phys,   rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);  /* We have now passed the point of no return.  The old core image has been   * forever lost, memory for a new core image has been allocated.  Set up   * and report new map.   */  if (sh_mp != NULL) {	/* Share the text segment. */	rmp->mp_seg[T] = sh_mp->mp_seg[T];  } else {	rmp->mp_seg[T].mem_phys = new_base;	rmp->mp_seg[T].mem_vir = 0;	rmp->mp_seg[T].mem_len = text_clicks;  }  rmp->mp_seg[D].mem_phys = new_base + text_clicks;  rmp->mp_seg[D].mem_vir = 0;  rmp->mp_seg[D].mem_len = data_clicks;  rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;  rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;  rmp->mp_seg[S].mem_len = stack_clicks;#if (CHIP == M68000)  rmp->mp_seg[T].mem_vir = 0;  rmp->mp_seg[D].mem_vir = rmp->mp_seg[T].mem_len;  rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir   	+ rmp->mp_seg[D].mem_len + gap_clicks;#endif  sys_newmap(who, rmp->mp_seg);   /* report new map to the kernel */  /* The old memory may have been swapped out, but the new memory is real. */  rmp->mp_flags &= ~(WAITING|ONSWAP|SWAPIN);  /* Zero the bss, gap, and stack segment. */  bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;  base = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;  bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;  base += bss_offset;  bytes -= bss_offset;  if ((s=sys_memset(0, base, bytes)) != OK) {	panic(__FILE__,"new_mem can't zero", s);  }  return(OK);}/*===========================================================================* *				patch_ptr				     * *===========================================================================*/PRIVATE void patch_ptr(stack, base)char stack[ARG_MAX];		/* pointer to stack image within PM */vir_bytes base;			/* virtual address of stack base inside user */{/* When doing an exec(name, argv, envp) call, the user builds up a stack * image with arg and env pointers relative to the start of the stack.  Now * these pointers must be relocated, since the stack is not positioned at * address 0 in the user's address space. */  char **ap, flag;  vir_bytes v;  flag = 0;			/* counts number of 0-pointers seen */  ap = (char **) stack;		/* points initially to 'nargs' */  ap++;				/* now points to argv[0] */  while (flag < 2) {	if (ap >= (char **) &stack[ARG_MAX]) return;	/* too bad */	if (*ap != NULL) {		v = (vir_bytes) *ap;	/* v is relative pointer */		v += base;		/* relocate it */		*ap = (char *) v;	/* put it back */	} else {		flag++;	}	ap++;  }}/*===========================================================================* *				insert_arg				     * *===========================================================================*/PRIVATE int insert_arg(stack, stk_bytes, arg, replace)char stack[ARG_MAX];		/* pointer to stack image within PM */vir_bytes *stk_bytes;		/* size of initial stack */char *arg;			/* argument to prepend/replace as new argv[0] */int replace;{/* Patch the stack so that arg will become argv[0].  Be careful, the stack may * be filled with garbage, although it normally looks like this: *	nargs argv[0] ... argv[nargs-1] NULL envp[0] ... NULL * followed by the strings "pointed" to by the argv[i] and the envp[i].  The * pointers are really offsets from the start of stack. * Return true iff the operation succeeded. */  int offset, a0, a1, old_bytes = *stk_bytes;  /* Prepending arg adds at least one string and a zero byte. */  offset = strlen(arg) + 1;  a0 = (int) ((char **) stack)[1];	/* argv[0] */  if (a0 < 4 * PTRSIZE || a0 >= old_bytes) return(FALSE);  a1 = a0;			/* a1 will point to the strings to be moved */  if (replace) {	/* Move a1 to the end of argv[0][] (argv[1] if nargs > 1). */	do {		if (a1 == old_bytes) return(FALSE);		--offset;	} while (stack[a1++] != 0);  } else {	offset += PTRSIZE;	/* new argv[0] needs new pointer in argv[] */	a0 += PTRSIZE;		/* location of new argv[0][]. */  }  /* stack will grow by offset bytes (or shrink by -offset bytes) */  if ((*stk_bytes += offset) > ARG_MAX) return(FALSE);  /* Reposition the strings by offset bytes */  memmove(stack + a1 + offset, stack + a1, old_bytes - a1);  strcpy(stack + a0, arg);	/* Put arg in the new space. */  if (!replace) {	/* Make space for a new argv[0]. */	memmove(stack + 2 * PTRSIZE, stack + 1 * PTRSIZE, a0 - 2 * PTRSIZE);	((char **) stack)[0]++;	/* nargs++; */  }  /* Now patch up argv[] and envp[] by offset. */  patch_ptr(stack, (vir_bytes) offset);  ((char **) stack)[1] = (char *) a0;	/* set argv[0] correctly */  return(TRUE);}/*===========================================================================* *				patch_stack				     * *===========================================================================*/PRIVATE char *patch_stack(fd, stack, stk_bytes, script)int fd;				/* file descriptor to open script file */char stack[ARG_MAX];		/* pointer to stack image within PM */vir_bytes *stk_bytes;		/* size of initial stack */char *script;			/* name of script to interpret */{/* Patch the argument vector to include the path name of the script to be * interpreted, and all strings on the #! line.  Returns the path name of * the interpreter. */  char *sp, *interp = NULL;  int n;  enum { INSERT=FALSE, REPLACE=TRUE };  /* Make script[] the new argv[0]. */  if (!insert_arg(stack, stk_bytes, script, REPLACE)) return(NULL);  if (lseek(fd, 2L, 0) == -1			/* just behind the #! */    || (n= read(fd, script, PATH_MAX)) < 0	/* read line one */    || (sp= memchr(script, '\n', n)) == NULL)	/* must be a proper line */	return(NULL);  /* Move sp backwards through script[], prepending each string to stack. */  for (;;) {	/* skip spaces behind argument. */	while (sp > script && (*--sp == ' ' || *sp == '\t')) {}	if (sp == script) break;	sp[1] = 0;	/* Move to the start of the argument. */	while (sp > script && sp[-1] != ' ' && sp[-1] != '\t') --sp;	interp = sp;	if (!insert_arg(stack, stk_bytes, sp, INSERT)) return(NULL);  }  /* Round *stk_bytes up to the size of a pointer for alignment contraints. */  *stk_bytes= ((*stk_bytes + PTRSIZE - 1) / PTRSIZE) * PTRSIZE;  close(fd);  return(interp);}/*===========================================================================* *				rw_seg					     * *===========================================================================*/PUBLIC void rw_seg(rw, fd, proc, seg, seg_bytes0)int rw;				/* 0 = read, 1 = write */int fd;				/* file descriptor to read from / write to */int proc;			/* process number */int seg;			/* T, D, or S */phys_bytes seg_bytes0;		/* how much is to be transferred? */{/* Transfer text or data from/to a file and copy to/from a process segment. * This procedure is a little bit tricky.  The logical way to transfer a * segment would be block by block and copying each block to/from the user * space one at a time.  This is too slow, so we do something dirty here, * namely send the user space and virtual address to the file system in the * upper 10 bits of the file descriptor, and pass it the user virtual address * instead of a PM address.  The file system extracts these parameters when  * gets a read or write call from the process manager, which is the only  * process that is permitted to use this trick.  The file system then copies  * the whole segment directly to/from user space, bypassing PM completely. * * The byte count on read is usually smaller than the segment count, because * a segment is padded out to a click multiple, and the data segment is only * partially initialized. */  int new_fd, bytes, r;  char *ubuf_ptr;  struct mem_map *sp = &mproc[proc].mp_seg[seg];  phys_bytes seg_bytes = seg_bytes0;  new_fd = (proc << 7) | (seg << 5) | fd;  ubuf_ptr = (char *) ((vir_bytes) sp->mem_vir << CLICK_SHIFT);  while (seg_bytes != 0) {#define PM_CHUNK_SIZE 8192	bytes = MIN((INT_MAX / PM_CHUNK_SIZE) * PM_CHUNK_SIZE, seg_bytes);	if (rw == 0) {		r = read(new_fd, ubuf_ptr, bytes);	} else {		r = write(new_fd, ubuf_ptr, bytes);	}	if (r != bytes) break;	ubuf_ptr += bytes;	seg_bytes -= bytes;  }}/*===========================================================================* *				find_share				     * *===========================================================================*/PUBLIC struct mproc *find_share(mp_ign, ino, dev, ctime)struct mproc *mp_ign;		/* process that should not be looked at */ino_t ino;			/* parameters that uniquely identify a file */dev_t dev;time_t ctime;{/* Look for a process that is the file <ino, dev, ctime> in execution.  Don't * accidentally "find" mp_ign, because it is the process on whose behalf this * call is made. */  struct mproc *sh_mp;  for (sh_mp = &mproc[0]; sh_mp < &mproc[NR_PROCS]; sh_mp++) {	if (!(sh_mp->mp_flags & SEPARATE)) continue;	if (sh_mp == mp_ign) continue;	if (sh_mp->mp_ino != ino) continue;	if (sh_mp->mp_dev != dev) continue;	if (sh_mp->mp_ctime != ctime) continue;	return sh_mp;  }  return(NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -