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

📄 memory.c

📁 一份精简的linux内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* no need for invalidate */	return page;}void un_wp_page(unsigned long *	table_entry)/*参数为页表项,若其所对应页非共享(引用计数为1)则将该页设为可写并返回 */{                                          /*若其所对应页为共享(引用计数大于1),则申请新页,并将原页内容复制进来 */	unsigned long old_page,new_page;	old_page = 0xfffff000 &	*table_entry;	if (old_page >=	LOW_MEM	&& mem_map[MAP_NR(old_page)]==1) { /*若该页被引用次数为1,则说明该页未被共享,直接将该页设为可写并返回 */		*table_entry |=	2;		invalidate();		return;	}	if (!(new_page=get_free_page()))/*若该页被引用次数大于1,则说明是共享页面,需申请新页 */		oom();/*内存不够处理 */	if (old_page >=	LOW_MEM)		mem_map[MAP_NR(old_page)]--;	*table_entry = new_page	| 7;	invalidate();	copy_page(old_page,new_page);/*复制页 */}	/* * This	routine	handles	present	pages, when	users try to write * to a	shared page. It	is done	by copying the page	to a new address * and decrementing	the	shared-page	counter	for	the	old	page. * * If it's in code space we	exit with a	segment	error. */void do_wp_page(unsigned long error_code,unsigned long address)/*写保护函数 */{#if	0/* we cannot do	this yet: the estdio library writes	to code	space *//* stupid, stupid. I really	want the libc.a	from GNU */	if (CODE_SPACE(address))/*若欲写进程的代码段,则直接中止进程*/		do_exit(SIGSEGV);#endif	un_wp_page((unsigned long *)		(((address>>10)	& 0xffc) + (0xfffff000 & /*给定线性地址转换为对应页表项物理地址 */		*((unsigned	long *)	((address>>20) &0xffc)))));}void write_verify(unsigned long	address)/*写页面验证,若该页不存在则直接退出(do_no_page会处理),参数为线性地址 */{                                    /*若该页存在且不可写则执行un_wp_page,否则直接退出*/	unsigned long page;	if (!( (page = *((unsigned long	*) ((address>>20) &	0xffc))	)&1))		return;	page &=	0xfffff000;	page +=	((address>>10) & 0xffc);	if ((3 & *(unsigned	long *)	page) == 1)	 /*	non-writeable, present */		un_wp_page((unsigned long *) page);	return;}void get_empty_page(unsigned long address)/*get_free_page加pute_page,参数为线性地址 */{	unsigned long tmp;	if (!(tmp=get_free_page()) || !put_page(tmp,address)) {		free_page(tmp);		/* 0 is	ok - ignored */		oom();	}}/* * try_to_share() checks the page at address "address" in the task "p", * to see if it	exists,	and	if it is clean.	If so, share it	with the current * task. * * NOTE! This assumes we have checked that p !=	current, and that they * share the same executable. */static int try_to_share(unsigned long address, struct task_struct *	p)/*address为逻辑地址(0-64mb)*/{                                /*若当前进程address处的页不存在则使当前进程共享进程p中adress处的页,若存在则出错*/	unsigned long from;	unsigned long to;	unsigned long from_page;	unsigned long to_page;	unsigned long phys_addr;	from_page =	to_page	= ((address>>20) & 0xffc);	from_page += ((p->start_code>>20) &	0xffc);/*获得p进程中逻辑地址address所在地址对应的目录项*/	to_page	+= ((current->start_code>>20) &	0xffc);/*获得当前进程中逻辑地址address所在地址对应的目录项*//* is there	a page-directory at	from? */	from = *(unsigned long *) from_page;	if (!(from & 1))		return 0;	from &=	0xfffff000;	from_page =	from + ((address>>10) &	0xffc);	phys_addr =	*(unsigned long	*) from_page;/*获得p进程中逻辑地址address所在地址对应的页表项的内容*//* is the page clean and present? */	if ((phys_addr & 0x41) != 0x01)/*p进程中逻辑地址address所在地址对应的物理页面是否存在且干净*/		return 0;	phys_addr &= 0xfffff000;/*获得p进程中逻辑地址address所在地址对应的物理页地址*/	if (phys_addr >= HIGH_MEMORY ||	phys_addr <	LOW_MEM)		return 0;	to = *(unsigned	long *)	to_page;	if (!(to & 1))/*若当前进程页目录项不存在则申请一新项*/		if (to = get_free_page())			*(unsigned long	*) to_page = to	| 7;		else			oom();	to &= 0xfffff000;	to_page	= to + ((address>>10) &	0xffc);	if (1 &	*(unsigned long	*) to_page) /*若当前进程address处的页已存在则出错*/		panic("try_to_share: to_page already exists");/* share them: write-protect */	*(unsigned long	*) from_page &=	~2;	*(unsigned long	*) to_page = *(unsigned	long *)	from_page; /*当前进程复制p进程的页表项*/	invalidate();	phys_addr -= LOW_MEM;	phys_addr >>= 12;	mem_map[phys_addr]++;	return 1;}/* * share_page()	tries to find a	process	that could share a page	with * the current one.	Address	is the address of the wanted page relative * to the current data space. * * We first	check if it	is at all feasible by checking executable->i_count. * It should be	>1 if there	are	other tasks	sharing	this inode. */static int share_page(unsigned long	address) /*尝试共享文件,adress为进程逻辑地址*/{                               /* 通过executable—>i_count(指针所指节点(进程运行的执行文件)的引用计数)来判断当前运行的程序是否有多个拷贝,若是则尝试他们之间的页面共享操作*/	struct task_struct ** p;	if (!current->executable)		return 0;	if (current->executable->i_count < 2)  /* 通过executable—>i_count(指针所指节点(进程运行的执行文件)的引用计数)来判断当前运行的程序是否有多个拷贝,若是则尝试他们之间的页面共享操作*/		return 0;	for	(p = &LAST_TASK	; p	> &FIRST_TASK ;	--p) {		if (!*p)			continue;		if (current	== *p)			continue;		if ((*p)->executable !=	current->executable)			continue;		if (try_to_share(address,*p))			return 1;	}	return 0;}void do_no_page(unsigned long error_code,unsigned long address) /*缺页处理,先尝试页面共享,若失败再从设备上读入相应页*/{	int	nr[4];	unsigned long tmp;	unsigned long page;	int	block,i;	address	&= 0xfffff000;	tmp	= address -	current->start_code; /*计算线性地址adress对应的进程逻辑地址(页起始地址)*/	if (!current->executable ||	tmp	>= current->end_data) { /*若exectuable为空(说明为进程0进程1)或地址超出进程代码数据段则说明申请的是堆栈*/		get_empty_page(address);		return;	}	if (share_page(tmp)) /*否则说明地址在执行文件范围内,尝试共享页面*/		return;	if (!(page = get_free_page())) /*若尝试共享文件失败,则申请一新页并从设备上读入文件数据*/		oom();/* remember	that 1 block is	used for header	*/	block =	1 +	tmp/BLOCK_SIZE;	for	(i=0 ; i<4 ; block++,i++)		nr[i] =	bmap(current->executable,block);	bread_page(page,current->executable->i_dev,nr); /*从设备上读入数据并存入新页中*/	i =	tmp	+ 4096 - current->end_data; /*若读如的是文件结尾数据(可能不足一页),则需将超出部分截去*/	tmp	= page + 4096;	while (i-- > 0)	{		tmp--;		*(char *)tmp = 0;	}	if (put_page(page,address)) /*将新页映射到进程线性地址中*/		return;	free_page(page);	oom();}void mem_init(long start_mem, long end_mem)/*主内存初始化*/{	int	i;	HIGH_MEMORY	= end_mem;	for	(i=0 ; i<PAGING_PAGES ;	i++)		 /*1-16mb的内存全标记为已使用(即mem_map数组中的对应项置位)*/						mem_map[i] = USED;							i =	MAP_NR(start_mem);		/*计算主内存起始位置的页号*/	end_mem	-= start_mem;	end_mem	>>=	12;	while (end_mem-->0)	   /*主内存中所有页面在mem_map数组中的对应项清0*/		mem_map[i++]=0;}void calc_mem(void) /*计算内存空闲页面数并显示*/{	int	i,j,k,free=0;	long * pg_tbl;	for(i=0	; i<PAGING_PAGES ; i++)		if (!mem_map[i]) free++;	printk("%d pages free (of %d)\n\r",free,PAGING_PAGES);	for(i=2	; i<1024 ; i++)	{		if (1&pg_dir[i]) {			pg_tbl=(long *)	(0xfffff000	& pg_dir[i]);			for(j=k=0 ;	j<1024 ; j++)				if (pg_tbl[j]&1)					k++;			printk("Pg-dir[%d] uses	%d pages\n",i,k);		}	}}

⌨️ 快捷键说明

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