操作系统与网络 2019-1-29

1.继续完成进程间通信

1.1 完成接收端的内存文件映射接受

1.在 Recv 端添加一个按钮 接收映射文件内存 ;
2.在 CRecvDlg::OnBnClickedButton3 函数中,打开内存文件映射: HANDLE h_mapping_file = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"HH") ;
3.获取成功则获取内存空间: wchar_t* pwsz_content = (wchar_t*)::MapViewOfFile(h_mapping_file, FILE_MAP_ALL_ACCESS, 0, 0, 4096) ;
4.不为空则进行拷贝: m_str_recv = pwsz_content ;
5.从调用进程的地址空间取消映射文件的映射视图: UnmapViewOfFile(pwsz_content) ;
6.关闭内存映射: ::CloseHandle(h_mapping_file) ; h_mapping_file = 0 ;

void CRecvDlg::OnBnClickedButton3()
{
	// 1. 打开内存文件映射
	HANDLE h_mapping_file = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"HH");
	if(h_mapping_file == 0)
	{
		MessageBox(L"文件映射打开失败");
		return;
	}

	// 2. 获取成功则获取内存空间
	wchar_t* pwsz_content = (wchar_t*)::MapViewOfFile(h_mapping_file, FILE_MAP_ALL_ACCESS, 0, 0, 4096);
	if(pwsz_content != 0)
	{
		// 不为空则进行拷贝
		m_str_recv = pwsz_content;
		UpdateData(FALSE);
	}

	// 
	UnmapViewOfFile(pwsz_content);

	// 关闭内存映射
	::CloseHandle(h_mapping_file);
	h_mapping_file = 0;
}

2.内存管理

2.1 对于一个32位操作系统来说,其前 64k 称为 空指针区域 ,不允许访问;从 64k 到 2GB ,称为 用户模式 ,即用户程序需要的内存空间在此分配;后 2GB 为 内核模式 ,即那些内核对象所在的位置。

2.2 连续空间分配

1.单一连续空间:内存在此方式下分为系统区和用户区;作业串行执行(一个作业包含若干个程序);
2.固定分配区域:最简单的一种多道程序存储管理方式;将用户内存空间划分为若干个固定大小的区域,每个分区只装入一道作业,当有空闲分区时,便可以再从外存的后备作业队列中,选择适当大小的作业装入该分区,程序可能太大而放不进任何一个分区中,这时使用覆盖技术;内部有空间浪费;
3.动态分区分配:不预先将内存划分,而是在进程装入内存时,根据进程的大小动态地建立分区;CPU出现空闲,操作系统就换出进程,装入新进程。由于新进程占用内存较小就会产生碎片;可以通过紧凑(Compaction)技术来解决,但碎片会越来越多;

2.3 非连续空间分配(现在常用)

1.页式管理:用户程序的地址空间被划分成若干固定大小的区域,称为“页”,相应地,内存空间分成若干个物理块,页和块的大小相等。可将用户程序的任一页放在内存的任一块中,实现了离散分配;
2.段式管理:页面是主存物理空间中划分出来的等长的固定区域。分页方式的优点是页长固定,因而便于构造页表、易于管理,且不存在外碎片。但分页方式的缺点是页长与程序的逻辑大小不相关。例如,某个时刻一个子程序可能有一部分在主存中,另一部分则在辅存中。这不利于编程时的独立性,并给换入换出处理、存储保护和存储共享等操作造成麻烦。另一种划分可寻址的存储空间的方法称为分段。段是按照程序的自然分界划分的长度可以动态改变的区域。通常,程序员把子程序、操作数和常数等不同类型的数据划分到不同的段中,并且每个程序可以有多个相同类型的段。 段表本身也是一个段,可以存在辅存中,但一般是驻留在主存中。将用户程序地址空间分成若干个大小不等的段,每段可以定义一组相对完整的逻辑信息。存储分配时,以段为单位,段与段在内存中可以不相邻接,也实现了离散分配。
3.段页式管理:段页式存储组织是分段式和分页式结合的存储组织方法,这样可充分利用分段管理和分页管理的优点。
(1) 用分段方法来分配和管理虚拟存储器。程序的地址空间按逻辑单位分成基本独立的段,而每一段有自己的段名,再把每段分成固定大小的若干页。
(2) 用分页方法来分配和管理实存。即把整个主存分成与上述页大小相等的存储块,可装入作业的任何一页。程序对内存的调入或调出是按页进行的。但它又可按段实现共享和保护。

3.继续任务管理器

3.1 给主对话框上添加控件

1.将对话框横向拉长,从上到下依次添加:两个 Edit 控件,两个 Text Control 控件(名字分别为PNAME和PID),一个 Text Control 控件(要查找的值),一个 Edit 控件,三个按钮控件,一个 List Control 控件,两个 Text 控件(要修改的地址,要修改的值)和两个 Edit 控件,一个按钮控件(修改);
2.给所有的 Edit 控件添加 value 变量,给 List 控件添加变量: CString m_str_pname ; DWORD m_dw_process_id ; DWORD m_dw_findvalue ; DWORD m_dw_changeaddr ; DWORD m_dw_changevalue ; CListCtrl m_ls_showaddr ;
3.将 List 控件的属性 View 更改为 report ;
4.将最上面两个 Edit 控件的 Read Only 属性修改为 True ;
5.给 List 控件的第一行插入一行语句: m_ls_showaddr.InsertColumn(0, L"搜索的结果:", 0, 450) ;
6.为了能够双击左边 List 控件中的某一行,并且将双击选中行的进程名和进程ID放到右侧最上面两个 Edit 控件中,我们需要给左边的 List 控件添加一个事件处理函数,右键 List 控件,选择添加事件处理函数,选择消息类型为 NM_DBCLICK ,类列表为主对话框的类;
7.在 CTaskManagerDlg::OnNMDblclkList2 函数中,首先获取双击选中的项: int index = pNMItemActivate->iItem ;
8.若有双击选中的项,则获取进程名和进程ID: m_str_pname = m_lsProcessInfo.GetItemText(index, 0) ;CString str_process_id ; str_process_id = m_lsProcessInfo.GetItemText(index, 1) ; m_dw_process_id = _wtoi(str_process_id) ;

void CTaskManagerDlg::OnNMDblclkList2(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	
	// 获取双击选中的项
	int index = pNMItemActivate->iItem;
	if(index != -1)			// 有双击选中的项
	{
		// 获取进程名
		m_str_pname = m_lsProcessInfo.GetItemText(index, 0);
		// 获取进程ID
		CString str_process_id;
		str_process_id = m_lsProcessInfo.GetItemText(index, 1);
		m_dw_process_id = _wtoi(str_process_id);

		// 更新数据
		UpdateData(FALSE);
	}

	*pResult = 0;
}

9.给项目添加一个C++类, CModifyMemory ,该类有一个成员变量: HANDLE m_hOpenPracess ,该变量在构造里置为零,在析构里进行关闭: ::CloseHandle(m_hOpenPracess) ; m_hOpenPracess = 0 ; 一个成员函数: bool OpenSelectProcess(DWORD processID) ;
10.在 CModifyMemory::OpenSelectProcess 函数中,我们首先判断 m_hOpenPracess 是否为 0 ,若是零,则可以打开进程,否则应该先关闭已打开的进程;

bool CModifyMemory::OpenSelectProcess 函数,并且在 主窗口的成员中(DWORD processID)
{
	if(m_hOpenPracess == 0)				// 若为空,则可以打开进程
	{
		// 打开进程
		m_hOpenPracess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
		if(m_hOpenPracess != NULL)
			return true;
	}
	else								// 若当前有进程打开,则先关闭打开的进程再打开新的进程
	{
		// 关闭已经打开的进程
		::CloseHandle(m_hOpenPracess);
		m_hOpenPracess = 0;
		m_hOpenPracess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
		if(m_hOpenPracess != NULL)
			return true;
	}
	return false;
}

11.在双击 List 控件的函数 CTaskManagerDlg::OnNMDblclkList2 中进行调用上述 bool CModifyMemory::OpenSelectProcess 函数,并且在主窗口中定义一个 CModifyMemory mm ;

void CTaskManagerDlg::OnNMDblclkList2(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	
	// 获取双击选中的项
	int index = pNMItemActivate->iItem;
	if(index != -1)			// 有双击选中的项
	{
		// 获取进程名
		m_str_pname = m_lsProcessInfo.GetItemText(index, 0);
		// 获取进程ID
		CString str_process_id;
		str_process_id = m_lsProcessInfo.GetItemText(index, 1);
		m_dw_process_id = _wtoi(str_process_id);

		// 打开进程
		if(mm.OpenSelectProcess(m_dw_process_id) == false)
		{
			m_str_pname = L"";
			m_dw_process_id = 0;
			MessageBox(L"进程打开失败");
		}

		// 更新数据
		UpdateData(FALSE);
	}

	*pResult = 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值