exec.c ( File view )

  • By 2010-08-31
  • View(s):24
  • Download(s):2
  • Point(s): 1
			/*
* linux/fs/exec.c
*
* (C) 1991 Linus Torvalds
*/

/*
* #!-checking implemented by tytso.
*/
/*
* #!开始的程序检测部分是由tytso 实现的。
*/

/*
* Demand-loading implemented 01.12.91 - no need to read anything but
* the header into memory. The inode of the executable is put into
* "current->executable", and page faults do the actual loading. Clean.
*
* Once more I can proudly say that linux stood up to being changed: it
* was less than 2 hours work to get demand-loading completely implemented.
*/
/*
* 需求时加载是于1991.12.1 实现的 - 只需将执行文件头部分读进内存而无须
* 将整个执行文件都加载进内存。执行文件的i 节点被放在当前进程的可执行字段中
* ("current->executable"),而页异常会进行执行文件的实际加载操作以及清理工作。
*
* 我可以再一次自豪地说,linux 经得起修改:只用了不到2 小时的工作时间就完全
* 实现了需求加载处理。
*/

#include <errno.h>		// 错误号头文件。包含系统中各种出错号。(Linus 从minix 中引进的)。
#include <string.h>		// 字符串头文件。主要定义了一些有关字符串操作的嵌入函数。
#include <sys/stat.h>		// 文件状态头文件。含有文件或文件系统状态结构stat{

}和常量。
#include <a.out.h>		// a.out 头文件。定义了a.out 执行文件格式和一些宏。

#include <linux/fs.h>		// 文件系统头文件。定义文件表结构(file,buffer_head,m_inode 等)。
#include <linux/sched.h>	// 调度程序头文件,定义了任务结构task_struct、初始任务0 的数据,
// 还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。
#include <linux/kernel.h>	// 内核头文件。含有一些内核常用函数的原形定义。
#include <linux/mm.h>		// 内存管理头文件。含有页面大小定义和一些页面释放函数原型。
#include <asm/segment.h>	// 段操作头文件。定义了有关段寄存器操作的嵌入式汇编函数。

extern int sys_exit (int exit_code);	// 程序退出系统调用。
extern int sys_close (int fd);	// 文件关闭系统调用。

/*
* MAX_ARG_PAGES defines the number of pages allocated for arguments
* and envelope for the new program. 32 should suffice, this gives
* a maximum env+arg of 128kB !
*/
/*
* MAX_ARG_PAGES 定义了新程序分配给参数和环境变量使用的内存最大页数。
* 32 页内存应该足够了,这使得环境和参数(env+arg)空间的总合达到128kB!
*/
#define MAX_ARG_PAGES 32

/*
* create_tables() parses the env- and arg-strings in new user
* memory and creates the pointer tables from them, and puts their
* addresses on the "stack", returning the new stack pointer value.
*/
/*
* create_tables()函数在新用户内存中解析环境变量和参数字符串,由此
* 创建指针表,并将它们的地址放到"堆栈"上,然后返回新栈的指针值。
*/
//// 在新用户堆栈中创建环境和参数变量指针表。
// 参数:p - 以数据段为起点的参数和环境信息偏移指针;argc - 参数个数;envc -环境变量数。
// 返回:堆栈指针。
static unsigned long *
create_tables (char *p, int argc, int envc)
{

  unsigned long *argv, *envp;
  unsigned long *sp;

// 堆栈指针是以4 字节(1 节)为边界寻址的,因此这里让sp 为4 的整数倍。
  sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
// sp 向下移动,空出环境参数占用的空间个数,并让环境参数指针envp 指向该处。
  sp -= envc + 1;
  envp = sp;
// sp 向下移动,空出命令行参数指针占用的空间个数,并让argv 指针指向该处。
// 下面指针加1,sp 将递增指针宽度字节值。
  sp -= argc + 1;
  argv = sp;
// 将环境参数指针envp 和命令行参数指针以及命令行参数个数压入堆栈。
  put_fs_long ((unsigned long) envp, --sp);
  put_fs_long ((unsigned long) argv, --sp);
  put_fs_long ((unsigned long) argc, --sp);
// 将命令行各参数指针放入前面空出来的相应地方,最后放置一个NULL 指针。
  while (argc-- > 0)
    {

      put_fs_long ((unsigned long) p, argv++);
      while (get_fs_byte (p++)) /* nothing */ ;	// p 指针前移4 字节。
    
}
  put_fs_long (0, argv);
// 将环境变量各指针放入前面空出来的相应地方,最后放置一个NULL 指针。
  while (envc-- > 0)
    {

      put_fs_long ((unsigned long) p, envp++);
      while (get_fs_byte (p++)) /* nothing */ ;
    
}
  put_fs_long (0, envp);
  return sp;			// 返回构造的当前新堆栈指针。

}

/*
* count() counts the number of arguments/envelopes
*/
/*
* count()函数计算命令行参数/环境变量的个数。
*/
//// 计算参数个数。
// 参数:argv - 参数指针数组,最后一个指针项是NULL。
// 返回:参数个数。
static int
count (char **argv)
{

  int i = 0;
  char **tmp;

  if (tmp = argv)
    while (get_fs_long ((unsigned long *) (tmp++)))
      i++;

  return i;

}

/*
* 'copy_string()' copies argument/envelope strings from user
* memory to free pages in kernel mem. These are in a format ready
* to be put directly into the top of new user memory.
*
* Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
* whether the string and the string array are from user or kernel segments:
*
* from_kmem argv * argv **
* 0 user space user space
* 1 kernel space user space
* 2 kernel space kernel space
*
* We do this by playing games with the fs segment register. Since it
* it is expensive to load a segment register, we try to avoid calling
* set_fs() unless we absolutely have to.
*/
/*
* 'copy_string()'函数从用户内存空间拷贝参数和环境字符串到内核空闲页面内存中。
* 这些已具有直接放到新用户内存中的格式。
*
* 由TYT(Tytso)于1991.12.24 日修改,增加了from_kmem 参数,该参数指明了字符串或
* 字符串数组是来自用户段还是内核段。
*
* from_kmem argv * argv **
* 0 用户空间 用户空间
* 1 内核空间 用户空间
* 2 内核空间 内核空间
*
* 我们是通过巧妙处理fs 段寄存器来操作的。由于加载一个段寄存器代价太大,所以
* 我们尽量避免调用set_fs(),除非实在必要。
*/
//// 复制指定个数的参数字符串到参数和环境空间。
// 参数:argc - 欲添加的参数个数;argv - 参数指针数组;page - 参数和环境空间页面指针数组。
// p -在参数表空间中的偏移指针,始终指向已复制串的头部;from_kmem - 字符串来源标志。
// 在do_execve()函数中,p 初始化为指向参数表(128kB)空间的最后一个长字处,参数字符串
// 是以堆栈操作方式逆向往其中复制存放的,因此p 指针会始终指向参数字符串的头部。
// 返回:参数和环境空间当前头部指针。
static unsigned long
copy_strings (int argc, char **argv, unsigned long *page,
	      unsigned long p, int from_kmem)
{

  char *tmp, *pag;
  int len, offset = 0;
  unsigned long old_fs, new_fs;

  if (!p)
    return 0;			/* bullet-proofing *//* 偏移指针验证 */
// 取ds 寄存器值到new_fs,并保存原fs 寄存器值到old_fs。
  new_fs = get_ds ();
  old_fs = get_fs ();
// 如果字符串和字符串数组来自内核空间,则设置fs 段寄存器指向内核数据段(ds)。
  if (from_kmem == 2)
    set_fs (new_fs);
// 循环处理各个参数,从最后一个参数逆向开始复制,复制到指定偏移地址处。
  while (argc-- > 0)
    {

// 如果字符串在用户空间而字符串数组在内核空间,则设置fs 段寄存器指向内核数据段(ds)。
      if (from_kmem == 1)
	set_fs (new_fs);
// 从最后一个参数开始逆向操作,取fs 段中最后一参数指针到tmp,如果为空,则出错死机。
      if (!(tmp = (char *) get_fs_long (((unsigned long *) argv) + argc)))
	panic ("argc is wrong");
// 如果字符串在用户空间而字符串数组在内核空间,则恢复fs 段寄存器原值。
      if (from_kmem == 1)
	set_fs (old_fs);
// 计算该参数字符串长度len,并使tmp 指向该参数字符串末端。
      len = 0;			/* remember zero-padding */
      do
	{
			/* 我们知道串是以NULL 字节结尾的 */
	  len++;
	
}
      while (get_fs_byte (tmp++));
// 如果该字符串长度超过此时参数和环境空间中还剩余的空闲长度,则恢复fs 段寄存器并返回0。
      if (p - len < 0)
	{
			/* this shouldn't happen - 128kB */
	  set_fs (old_fs);	/* 不会发生-因为有128kB 的空间 */
	  return 0;
	
}
// 复制fs 段中当前指定的参数字符串,是从该字符串尾逆向开始复制。
      while (len)
	{

	  --p;
	  --tmp;
	  --len;
// 函数刚开始执行时,偏移变量offset 被初始化为0,因此若offset-1<0,说明是首次复制字符串,
// 则令其等于p 指针在页面内的偏移值,并申请空闲页面。
	  if (--offset < 0)
	    {

	      offset = p % PAGE_SIZE;
// 如果字符串和字符串数组在内核空间,则恢复fs 段寄存器原值。
	      if (from_kmem == 2)
		set_fs (old_fs);
// 如果当前偏移值p 所在的串空间页面指针数组项page[p/PAGE_SIZE]==0,表示相应页面还不存在,
// 则需申请新的内存空闲页面,将该页面指针填入指针数组,并且也使pag 指向该新页面,若申请不
// 到空闲页面则返回0。
	      if (!(pag = (char *) page[p / PAGE_SIZE]) &&
		  !(pag = (char *) page[p / PAGE_SIZE] =
		    (unsigned long *) get_free_page ()))
		return 0;
// 如果字符串和字符串数组来自内核空间,则设置fs 段寄存器指向内核数据段(ds)。
	      if (from_kmem == 2)
		set_fs (new_fs);

	    
}
// 从fs 段中复制参数字符串中一字节到pag+offset 处。
	  *(pag + offset) = get_fs_byte (tmp);
	
}
    
}
// 如果字符串和字符串数组在内核空间,则恢复fs 段寄存器原值。
  if (from_kmem == 2)
    set_fs (old_fs);
// 最后,返回参数和环境空间中已复制参数信息的头部偏移值。
  return p;

}

//// 修改局部描述符表中的描述符基址和段限长,并将参数和环境空间页面放置在数据段末端。
// 参数:text_size - 执行文件头部中a
...
...
(Not finished, please download and read the complete file)
			
...
Expand> <Close

Want complete source code? Download it here

Point(s): 1

Download
0 lines left, continue to read
Sponsored links

File list

Tips: You can preview the content of files by clicking file names^_^
Name Size Date
linux0.00 B0% 04-10-07
<boot>0.00 B04-10-07 15:01
bootsect.s12.49 kB08-01-04 21:38
head.s13.22 kB08-01-04 21:38
setup.s12.42 kB08-01-04 21:38
<fs>0.00 B04-10-07 15:01
bitmap.c8.46 kB02-09-04 13:12
block_dev.c3.95 kB02-09-04 13:12
buffer.c17.71 kB02-09-04 13:12
char_dev.c4.09 kB02-09-04 13:12
exec.c18.90 kB02-09-04 13:12
fcntl.c3.33 kB02-09-04 13:12
file_dev.c4.82 kB02-09-04 13:12
file_table.c209.00 B02-09-04 13:12
inode.c14.92 kB02-09-04 13:12
ioctl.c1.94 kB02-09-04 13:12
Makefile6.80 kB08-01-04 21:45
namei.c37.20 kB02-09-04 13:12
open.c10.00 kB02-09-04 13:12
pipe.c5.42 kB02-09-04 13:12
read_write.c5.86 kB02-09-04 13:12
stat.c2.69 kB02-09-04 13:12
super.c13.57 kB02-09-04 13:12
truncate.c2.46 kB02-09-04 13:12
<include>0.00 B04-10-07 15:01
a.out.h8.22 kB02-09-04 13:14
<asm>0.00 B04-10-07 15:01
io.h772.00 B02-09-04 13:14
memory.h1.03 kB08-01-04 22:13
segment.h2.50 kB02-09-04 13:14
system.h4.08 kB02-09-04 13:14
const.h589.00 B02-09-04 13:14
ctype.h1.68 kB02-09-04 13:14
errno.h2.30 kB02-09-04 13:14
fcntl.h3.30 kB02-09-04 13:14
<linux>0.00 B04-10-07 15:01
config.h2.16 kB02-09-04 13:14
fs.h9.72 kB02-09-04 13:14
hdreg.h2.94 kB02-09-04 13:14
head.h760.00 B02-09-04 13:14
kernel.h1.44 kB02-09-04 13:14
mm.h473.00 B02-09-04 13:14
sched.h13.25 kB02-09-04 13:14
sys.h5.41 kB02-09-04 13:14
tty.h3.93 kB02-09-04 13:14
signal.h4.01 kB02-09-04 13:14
stdarg.h1.77 kB02-09-04 13:14
stddef.h378.00 B02-09-04 13:14
string.h21.75 kB02-09-04 13:14
<sys>0.00 B04-10-07 15:01
stat.h2.37 kB02-09-04 13:14
times.h377.00 B02-09-04 13:14
types.h1.10 kB02-09-04 13:14
utsname.h423.00 B02-09-04 13:14
wait.h1.48 kB02-09-04 13:14
termios.h13.58 kB02-09-04 13:14
time.h1.81 kB02-09-04 13:14
unistd.h9.21 kB02-09-04 13:14
utime.h392.00 B02-09-04 13:14
<init>0.00 B04-10-07 15:01
main.c12.52 kB02-09-04 13:12
<kernel>0.00 B04-10-07 15:01
asm.s5.10 kB08-01-04 22:48
<blk_drv>0.00 B04-10-07 15:01
blk.h5.69 kB02-09-04 13:14
floppy.c23.49 kB02-09-04 13:12
hd.c17.14 kB02-09-04 13:12
ll_rw_blk.c7.59 kB02-09-04 13:12
Makefile4.25 kB08-01-04 22:53
ramdisk.c6.13 kB02-09-04 13:12
<chr_drv>0.00 B04-10-07 15:01
console.c30.91 kB02-09-04 13:12
keyboard.S21.04 kB08-01-04 22:59
Makefile4.81 kB08-01-04 22:59
rs_io.s5.75 kB08-01-04 22:59
serial.c2.91 kB02-09-04 13:12
tty_io.c18.40 kB02-09-04 13:12
tty_ioctl.c10.70 kB02-09-04 13:12
exit.c8.08 kB02-09-04 13:12
fork.c6.78 kB15-07-07 22:10
<math>0.00 B04-10-07 15:01
Makefile3.21 kB08-01-04 23:01
math_emulate.c2.08 kB02-09-04 13:12
mktime.c2.72 kB02-09-04 13:12
panic.c952.00 B02-09-04 13:12
printk.c1.75 kB02-09-04 13:12
sched.c18.57 kB16-07-07 21:23
signal.c5.61 kB02-09-04 13:12
sys.c7.62 kB02-09-04 13:12
system_call.s12.53 kB08-01-04 22:48
traps.c8.29 kB04-10-07 14:57
vsprintf.c9.96 kB02-09-04 13:12
<lib>0.00 B04-10-07 15:01
close.c397.00 B02-09-04 13:12
ctype.c1.72 kB02-09-04 13:12
dup.c401.00 B02-09-04 13:12
errno.c66.00 B02-09-04 13:12
execve.c607.00 B02-09-04 13:12
Makefile4.83 kB08-01-04 22:30
malloc.c13.50 kB02-09-04 13:12
open.c1.22 kB02-09-04 13:12
setsid.c382.00 B02-09-04 13:12
string.c199.00 B02-09-04 13:12
wait.c774.00 B02-09-04 13:12
write.c545.00 B02-09-04 13:12
_exit.c616.00 B02-09-04 13:12
Makefile8.58 kB08-01-04 22:21
<mm>0.00 B04-10-07 15:01
Makefile2.91 kB08-01-04 22:34
memory.c25.10 kB02-09-04 13:12
page.s842.00 B08-01-04 22:34
<tools>0.00 B04-10-07 15:01
build.c8.12 kB02-09-04 13:12
...
Sponsored links

exec.c (286.77 kB)

Need 1 point
Your Point(s)

Your Point isn't enough.

Get point immediately by PayPal

More(Debit card / Credit card / PayPal Credit / Online Banking)

Submit your source codes. Get more point

LOGIN

Don't have an account? Register now
Need any help?
Mail to: support@codeforge.com

切换到中文版?

CodeForge Chinese Version
CodeForge English Version

Where are you going?

^_^"Oops ...

Sorry!This guy is mysterious, its blog hasn't been opened, try another, please!
OK

Warm tip!

CodeForge to FavoriteFavorite by Ctrl+D