操作系统实验:线程的创建与撤销

一、实验目的

(1)熟悉windows系统提供的线程创建与撤销系统调用。
(2)掌握windows系统环境下线程的创建与撤销方法。
(3)掌握CreateThread()函数和ExitThread()函数。 

二、实验准备

(1).实验在windows XP,VC++6.0环境下进行。在这一步,安装了Windows XP虚拟机,学会了创建一个控制台工程文件。

(2).百度句柄的含义:句柄(handle),有多种意义,第一种解释:句柄是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。句柄是Windows用来标志应用程序中建立的或是适用的对象的唯一整数,Windows大量使用了句柄来标识对象。

(3).参照实验指导学习函数原型--CreateThread()函数:--线程创建
	HANDLE CreateThread(
  		LPSECURITY_ATTRIBUTES   IpThreadAttributes,
  		DWORD                   dwStackSize,
  		LPTHREAD_START_ROUTINE  IpStartAddress,
  		LPVOID 					IpParameter,
  		DWORD                   dwCreationFlags,
  		LPDWORD                 IpThreadId
  	);
	!!!实例化:HANDLE h1 = CreateThread( NULL, 0, Fun1, NULL, 0, NULL );
	<1>.参数IpThreadAttributes指定线程安全属性,当其为NULL时,则线程获取默认安全描述符。
	<2>.参数dwStackSize指定线程堆栈的初始大小,以字节为单位。如果此参数为0,则新线程使用可执行文件的默认大小。
	<3>.参数IpStartAddress指定由线程执行的自定义函数的指针。
	<4>.参数IpParameter指定自定义函数的参数。
	<5>.参数dwCreationFlags指定线程创建后所处的状态。该值为0,表示线程创建后立即执行。
	<6>.参数IpThreadId指定接收线程标识符的变量的指针。该参数为 NULL,则不返回线程标识符。
	---如果函数成功,则返回值是新线程的句柄。如果函数失败,则返回值为NULL。
	
(4).参照实验指导学习函数原型--ExitThread()函数:--撤销进程
	<1>.ExitThread()用于撤销当前进程。
	<2>.该函数没有返回值。
	<3>.用法举例:ExitThread(0);//参数0表示要撤销进程中的所有线程
	
(5).参照实验指导学习函数原型--TerminateThread()函数:--终止线程
	TerminateThread()用于终止当前线程。该函数与ExitThread()的区别在于,ExitThread()在撤销线程时将该线程所拥有的资源全部归还给系统,而TerminateThread()不归还资源。在实验中用ExitThread()函数居多。
	
(6).参照实验指导学习函数原型--Sleep()函数:--挂起线程
	该函数没有返回值。
	
(7).参照实验指导学习函数原型--CloseHandle()函数:--关闭句柄
	返回值:如果函数调用成功,则返回值为非0值;如果函数调用失败,则返回值为0.若要得到更多的错误信息,调用函数GetLastError()查询。

三、实验内容

(一)实验内容
实验1.使用系统调用CreatThread()创建一个子线程,并在子线程中显示;Thread is Running!.为了能让用户清楚地看到线程的运行情况,使用Sleep()使线程挂起5s,之后使用ExitThread(0)撤销进程.

实验2.模仿教学视频中的程序,改写一个吃苹果进程,采用多线程‘吃苹果’与单一线程‘吃苹果’做对比。了解多线程的运行原理。
(二)主要代码:

实验一:

#include "stdafx.h"
#include "01.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

void ThreadName1();
static HANDLE hHandle1=NULL;
DWORD dwThreadID1;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	hHandle1 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
		0,
		(LPTHREAD_START_ROUTINE) ThreadName1,
		(LPVOID) NULL,
		0, &dwThreadID1 );
	Sleep(5000);
	CloseHandle(hHandle1);
	ExitThread(0);

	return nRetCode;
}

void ThreadName1()
{
	printf("Thread is running!");
}

实验二:

#include "stdafx.h"
#include "011.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CWinApp theApp;

using namespace std;

void eatApple(int number){
	Sleep((3 - number)*1000);
	printf("I'm eatting #%d apples.\n",number);
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	HANDLE h1 = NULL;
	HANDLE h2 = NULL;
	HANDLE h3 = NULL;
	DWORD Th1 = NULL;
	DWORD Th2 = NULL;
	DWORD Th3 = NULL;

	int a=0;
	int b=1;
	int c=2;
	h1 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
		0,
		(LPTHREAD_START_ROUTINE) eatApple,
		(LPVOID) a,
		0, &Th1 );
	h2 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
		0,
		(LPTHREAD_START_ROUTINE) eatApple,
		(LPVOID) b,
		0, &Th2 );
	h3 = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
		0,
		(LPTHREAD_START_ROUTINE) eatApple,
		(LPVOID) c,
		0, &Th3 );

	eatApple(a);
	eatApple(b);
	eatApple(c);
	
	ExitThread(0);
	return nRetCode;
}

四、实验结果与总结

实验一总结:
   在Windows系统中进程是资源的拥有者,线程是系统调用的基本单位。  
   进程创建后,其主线程也随即被创建。在该实验中,有创建了一个名为  
   ThreadName1的子线程,该子线程与主线程并并发的被系统调度。  
   为了能让用户清楚地看到线程的运行情况,在主线程创建了子线程之后,  
   将主线程挂起5s,以确保子线程能够运行完毕,
   之后调用ExitThread(0)将所有线程撤销。

在这里插入图片描述
在这里插入图片描述

实验二总结:
   在该实验中,创建了Th1 Th2 Th3三个子线程,为了能清楚地看到线程的运行情况,在主线程创建了子线程之后,
   打印“I'm eatting apples”以确保能够直观的看出运行情况,
   之后调用ExitThread(0)将所有线程撤销。
   ExitThread(0)的使用:
   	void eatApple(int number){
	Sleep((3 - number)*1000);
	printf("I'm eatting #%d apples.\n",number);
		while(1){
			printf("#%d is exiting.\n\n",number);
			ExitThread(0);
		}
	}
PS:视频中用的是这种方法,但是我在学习文档中看到ExitThread(0)表示要撤销进程中的所有线程。所以我没用视频中的方法,直接在代码后面加了“ExitThread(0);”语句。

在这里插入图片描述
在这里插入图片描述

  • 16
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
实验目的 (1)掌握Windows系统提供的线创建撤销系统调用 (2)掌握Windows系统环境下线程的创建撤销方法 2 实验准备知识 (1)线创建 CreateThread()完成线程的创建。它在调用进程的地址空间上创建一个线程,执行指定的函数,并返回新建立线程的句柄。 原型: HANDLE CreateThread(   LPSECURITY_ATTRIBUTES lpThreadAttributes,   DWORD dwStackSize,   LPTHREAD_START_ROUTINE lpStartAddress,   LPVOID lpParameter,   DWORD dwCreationFlags,   LPDWORD lpThreadId);   参数说明:   lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。   dwStackSize,线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。   lpStartAddress,指向线程函数的指针,形式:@函数名,函数名称没有限制,但是必须以下列形式声明:   DWORD WINAPI ThreadProc (LPVOID pParam) ,格式不正确将无法调用成功。   lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL。   dwCreationFlags :线程标志,可取值如下   CREATE_SUSPENDED: 创建一个挂起的线程   0 :创建后立即激活。   lpThreadId:保存新线程的id。   返回值:   函数成功,返回线程句柄;函数失败返回false。 (2)撤销线程 ExitThread()用于撤销当前线程 原型: VOID ExitThread( DWORD dwExitCode ); 参数说明: DwExitCode:指定线程返回码 返回值: 该函数没有返回值 用法举例: ExitThread(0); (3)挂起线程 Sleep()用于挂起当前正在执行的线程 原型: VOID Sleep( DWORD dwMilliseconds ); 参数说明: dwMilliseconds:指定挂起时间,单位为ms(毫秒)。 返回值: 该函数没有返回值。 (4)关闭句柄 函数CloseHandle()用于关闭已打开对象的句柄,其作用与释放动态申请的内存空间类似,这样可以释放系统资源,使进程安全运行。 原型: BOOL CloseHandle( HANDLE hObject ); 参数说明: hObject:已打开对象的句柄。 返回值: 成功,返回值为非0值;失败,则返回值为0.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

司马道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值