Windows下创建进程和线程

Windows下创建进程和线程
Windows下创建进程和线程

摘要

参照课程中所提供的方法,实现了Windows下,基于Console控制台模式的进程及线程的创建.

Abstract:

By the reference of passage [1], realize the creation of threads and processes under the console mode, with the usage of win32 APIs.

关键词Win32 APIs,进程创建,线程创建.

Key Words:Win32 APIs,Process Creation,Thread Creation

目录

第一章前言 (3)

第二章windows进程与线程原理 (4)

第三章进程线程实现 (11)

1实验准备 (11)

2 Windows下进程的创建 (12)

3 Windows线程的创建及实验 (17)

3.1使用CreateThread在Windows下创建线程 (17)

3.2线程实验1---创建N个随机线程,所有线程的执行时间均为T秒,观察每个线程的运行状况 (19)

3.3线程实验2---Windows下可创建的线程的数目的测试 (24)

3.4线程实验3---最简单的一个临界资源的读者,写者程序. (26)

3.5几点说明 (29)

第四章应用及推广 (30)

参考文献 (31)

第一章前言

谈到在Windows创建线程的例子,在网上的很多的参考都是基于MFC的。其实,就操作系统实验这个前提而言,大可不必去碰那个大型的MFC的框架。中提到了在Windows命令控制台下创建进程及线程的方法,本文对中的方法加以了实现,并做些简单的进程及线程的测试程序.

第二章windows进程与线程原理

进程是不活泼的。若要使进程完成某项操作,它必须至少拥有一个线程,该线程负责执行包含在进程的地址空间中的代码。实际上,单个进程可能包含若干个线程,所有这些线程都“同时”执行进程地址空间中的代码。为此,每个线程都有它自己的一组CPU寄存器和它自己的堆栈。每个进程至少拥有一个线程,来执行进程的地址空间中的代码。当创建一个进程时,系统会自动创建它的第一个线程,称为主线程。然后,该线程可以创建子线程,而这些子线程又能创建更多的子线程。Windows 进程操作相关API:CreateProcess():进程创建

ExitProcess()或TerminateProcess():进程退出

ExitProcess()终止一个进程和它的所有线程;它的终止操作是完整的,包括关闭所有对象句柄、它的所有线程等;TerminateProcess()终止指定的进程和它的所有线程;它的终止操作是不完整的(如不向相关DLL通报关闭情况),通常只用于异常情况下对进程的终止。

线程线程(thread):是为了提高系统内程序的并发执行程度而提出来的概念,它是比进程更小的能够独立运行的基本单位。线程是一个轻量级实体(light-weight entity),它的结构(thread structure)相对简单,在切换速度上非常得快,同一进程中的线程切换不会引起进程的切换,对于并行计算来讲,有效的利用线程能够改善计算的效率,简化计算复杂性。

线程的调度、优先级和亲缘性

使用VC++6.0的Spy++这个工具,可以查看进程中线程的情况:

线程的优先级

每个线程都会被赋予一个从0(最低)到3 1(最高)的优先级号码。

高优先级线程将抢在低优先级线程之前运行,不管低优先级线程正在运行什么。

当设计一个应用程序时,你应该考虑到还有什么别的应用程序会与你的应用程序一道运行。然后,应该根据你的应用程序中的线程应该具备何种响应性,选择一个优先级类。

一旦选定了优先级类之后,就不必考虑你的应用程序与其他应用程序之间的关系,只需要集中考虑你的应用程序中的各个线程的相对优先级。

Windows支持6个优先级类:

Windows支持7个相对的线程优先级

亲缘性

按照默认设置,当系统将线程分配给处理器时, Windows2K/XP/2003使用软亲缘性来进行操作。这意味着如果所有其他因素相同的话,它将设法在它上次运行的那个处理器上运行线程。让线程留在单个处理器上,有助于重复使用仍然在处理器的内存高速缓存中的数据。

第三章进程线程实现

1实验准备

要实验的Windows下的多线程实验,应做如下准备

a)在新建中选”Win32 Console Application”àAn empty project

b) 选”工程”à”设置”选项,在”设置”中选择“C/C++”标签,在”Project Option”中,将”MLd”参数改成“MTd”(如图1).

图1

以上两步对实验成功至关重要,否则,即是代码无误,在连接时同样会出现问题。

2 Windows下进程的创建

在中,Windows的进程和线程模型被描述成”多进程,基于单进程的多线程”.在创建一个线程时,Windows会做大量的工作---创建一个新的地址空间,为进程分配资源以及创建一个基线程.

CreateProcess函数的原型如下

CreateProcess(

LPCTSTR lpApplicationName,

//pointer to name of executable moudle

LPTSTR cmdLine,

//pointer to command line string

LPSECURITY_ATTRIBUTES lpProcessAttributes,

//pointer to process security attributes LPSECURITY_ATTRIBUTES lpThreadAttributes,

//pointer to theread security attributes

BOOL bInheritHandle ,

//handle inheritance flag

DWORD dwCreationFlag,

//various creation flags

LPVOID lpEnviroment,//Enviroment variable

LPCTSTR lpCurrentDirectory,

//Child's current directory

LPSTARTUPINFO lpStartupInfo,

//pointer to StartupInfo

LPPROCESS_INFORMATION lpProcessInformation

//pointer to

PROCESS_INFORMATION

)

虽然参数多了些,不过在现阶段的实验级别,大多数参数只要用默认值即可。

下面要做的关于Windows使用进程的实验,在Linux系统下,可以使用类似execve(char* cmdName , char* cmdArgu)的语句从一个程序中去执行其它的

程序。

而如果在Windows下,当使用CreateProcess去执行相应的功能时,只要去改变cmdLine中的内容即可,其它的参数使用默认值,具体见代码1:代码1执行的功能是从命令行中启动这个名叫的launch的测试程序,在launch后面应加上保存有需要打开程序路径的文件名

如在命令行中键入

>launch set.txt

而set.txt中的内容为

C:\\WINDOWS\\SYSTEM32\\CALC.EXE

C:\\WINDOWS\\SYSTEM32\\NOTEPAD.EXE NEW.TXT

C:\\WINDOWS\\SYSTEM32\\CHARMAP.EXE

路径的前半部分为”C:\\WINDOWS\\”,这当然要视你的Windows系统的类型以及系统盘的存放位置而定。如果是NT或2000的机器,则应使用WINNT.

测试程序1:

示例如何使用进程的launch程序,通过在命令行中加载相应的命令文件,去按照命令文件中指定的程序路径打开相应的程序去执行*/

#include

#include

#include

#define MAX_LINE_LEN 80

int main(int argc,char* argv)

{

//local variables

FILE* fid;

char cmdLine[MAX_LINE_LEN];

//CreateProcess parameters

LPSECURITY_ATTRIBUTES processA=NULL;//Default

LPSECURITY_ATTRIBUTES threadA=NULL;//Default

BOOL shareRights=TRUE;//Default

DWORD creationMask=CREATE_NEW_CONSOLE;

//Window per process.

LPVOID enviroment=NULL;//Default

LPSTR curDir=NULL;//Default

STARTUPINFO startInfo;//Result

PROCESS_INFORMATION procInfo;//Result

//1.Read the command line parameters

if(argc!=2)

{

fprintf(stderr,"Usage:lanch\n");

exit(0);

}

//2.Open a file that coutain a set of commands

fid=fopen(argv[1],"r");

//3.For every command in the launch file

while(fgets(cmdLine,MAX_LINE_LEN,fid)!=NULL)

{

//Read a command from the file

if(cmdLine[strlen(cmdLine)-1]=='\n')

cmdLine[strlen(cmdLine)-1]='\0';//Remove NEWLINE

//Create a new process to execute the command

ZeroMemory(&startInfo,sizeof(startInfo));

startInfo.cb=sizeof(startInfo);

if(!CreateProcess(

NULL,//File name of executable

cmdLine,//command line

processA,//Process inherited security

threadA, //Thread inherited security

shareRights,//Rights propagation

creationMask,//various creation flags

enviroment,//Enviroment variable

curDir, //Child's current directory

&startInfo,

&procInfo

)

)

{

fprintf(stderr,"CreatProcess failed on

error %d\n",GetLastError);

ExitProcess(0);

}

}

//Terminate after all commands have finished.

return 0;

}

通过上面这段极其简洁的代码,完成了看似有些难度的任务,让我们充分感受到采用一些高级的编程手段所带来的便捷与高效.

3 Windows线程的创建及实验

3.1使用CreateThread在Windows下创建线程

在Windows中创建线程可以调用两个函数_beginthreadex和CreateThread两个函数.

这里只介绍后者.

CreateThread函数原型

HANDLE CreateThread

(LPSECURITY_ATTRIBUTES lpThreadAttributes,//pointer to thread security attributes

DWORD dwStackSize,//initial thread stack size, in bytes LPSECURITY_START_ROUTINE lpStartAddress,//pointer to thread function

LPVOID lpParameter,//argument for new thread

DWORD dwCreationFlags,//creation flags

LPDWORD lpThreadId //pointer to returned thread identifier

)

其中,在本实验阶段比较重要的参数是第三和第四个

a)第三个参数是一个指向函数的指针,所以应传入的参数应为函数的地址,如&Func的形式.

而这个传入的参数,则必须被声明成为

DWORD WINAPI threadFunc(LPVOID threadArgu);

的形式.这个函数也就是要执行线程任务的那个函数体实体.这里应注意,传入应使用Func而非&Func。

如:CreateThread(NULL,0,Fun c,…)

具体原因:我目前认为是系函数前部使用WINAPI所致。

b)第四个参数应是执行线程任务的函数体实体所需要的参数,即上面所举例的函数threadFunc的参数threadArgu,这在WINDOWS中被定义成一个LPVOID 的类型,目前我认为,可以把它在功能上看成和void* 类似。

参考:LPVOID的原型

typedef void far *LPVOID;

所以,当你有自己需要的类型的参数传入时,可以用

typedef struct

{

int firstArgu,

long secArgu,

}myType,* pMyType;

将你想要传入的参数装入一个结构体中。

在传入点,使用类似

pMyType pMyTpeyArgu;

CreateThread(NULL,0,threadFunc,pMyTypeArgu,…);

在函数threadFunc内部的接收点,可以使用“强行转换”,如

int intValue=((pMyType)lpvoid)->firstArgu;

long longValue=((pMyType)lpvoid)->secArgu;

… …

3.2线程实验1---创建N个随机线程,所有线程的执行时间均为T秒,观察每个线程的运行状况

为了使线程的运行趋于随机化,应先使用

srand((unsigned int)time (NULL));

在每个线程的运行中,每个线程的睡眠时间为

sleepTime=1000+30*(int)eRandom(50+tNo);

Sleep(sleepTime);

这样,可以使进程的运行趋于随机化.

/*测试程序2

创建N个随机线程的随机实验.

命令行输入参数

test threadNo runSecs

*/

#include

#include

#include

#include

#include

#define N 5

#define Type float

static int runFlag=TRUE;

DWORD WINAPI threadWork(LPVOID threadNo);

int parseArgToInt(char* inNumChar);

Type eRandom(int upLimit);

typedef struct

{

int data;

}INTEGER;

void main(int argc,char* argv)

{

unsigned int runTime;

int i;

int threadNum;

//int N;

SYSTEMTIME now;

WORD stopTimeMinute,stopTimeSecond;

DWORD targetThreadID;

//Get command line argument,N

if(argc!=3)

{

printf("please enter:NThread \n");

return;

}

threadNum=parseArgToInt(argv[1]);

runTime=parseArgToInt(argv[2]);

//Get the time the threads should run,runtime

//Calculate time to halt

// runTime=60;/*in seconds.*/

GetSystemTime(&now);

printf("mthread:Suite starting aty system

time%d,%d,%d\n",now.wHour,now.wMinute,now.wSecond);

stopTimeSecond=(now.wSecond+(WORD)runTime)%60;

stopTimeMinute=now.wMinute+(now.wSecond+(WORD)runTime)/60;

//FOR 1 TO N

INTEGER* tmpInt;

实验2-2windows2000 线程同步

实验2 并发与调度 2.2 Windows 2000线程同步 (实验估计时间:120分钟) 背景知识 实验目的 工具/准备工作 实验内容与步骤 背景知识 Windows 2000提供的常用对象可分成三类:核心应用服务、线程同步和线程间通讯。其中,开发人员可以使用线程同步对象来协调线程和进程的工作,以使其共享信息并执行任务。此类对象包括互锁数据、临界段、事件、互斥体和信号等。 多线程编程中关键的一步是保护所有的共享资源,工具主要有互锁函数、临界段和互斥体等;另一个实质性部分是协调线程使其完成应用程序的任务,为此,可利用内核中的事件对象和信号。 在进程内或进程间实现线程同步的最方便的方法是使用事件对象,这一组内核对象允许一个线程对其受信状态进行直接控制 (见表4-1) 。 而互斥体则是另一个可命名且安全的内核对象,其主要目的是引导对共享资源的访问。拥有单一访问资源的线程创建互斥体,所有想要访问该资源的线程应该在实际执行操作之前获得互斥体,而在访问结束时立即释放互斥体,以允许下一个等待线程获得互斥体,然后接着进行下去。 与事件对象类似,互斥体容易创建、打开、使用并清除。利用CreateMutex() API 可创建互斥体,创建时还可以指定一个初始的拥有权标志,通过使用这个标志,只有当线程完成了资源的所有的初始化工作时,才允许创建线程释放互斥体。

为了获得互斥体,首先,想要访问调用的线程可使用OpenMutex() API来获得指向对象的句柄;然后,线程将这个句柄提供给一个等待函数。当内核将互斥体对象发送给等待线程时,就表明该线程获得了互斥体的拥有权。当线程获得拥有权时,线程控制了对共享资源的访问——必须设法尽快地放弃互斥体。放弃共享资源时需要在该对象上调用ReleaseMute() API。然后系统负责将互斥体拥有权传递给下一个等待着的线程(由到达时间决定顺序) 。 实验目的 在本实验中,通过对事件和互斥体对象的了解,来加深对Windows 2000线程同步的理解。 1) 回顾系统进程、线程的有关概念,加深对Windows 2000线程的理解。 2) 了解事件和互斥体对象。 3) 通过分析实验程序,了解管理事件对象的API。 4) 了解在进程中如何使用事件对象。 5) 了解在进程中如何使用互斥体对象。 6) 了解父进程创建子进程的程序设计方法。 工具/准备工作 在开始本实验之前,请回顾教科书的相关内容。 您需要做以下准备: 1) 一台运行Windows 2000 Professional操作系统的计算机。 2) 计算机中需安装Visual C++ 6.0专业版或企业版。 实验内容与步骤 1. 事件对象 2. 互斥体对象 1. 事件对象 清单2-1程序展示了如何在进程间使用事件。父进程启动时,利用CreateEvent() API创建一个命名的、可共享的事件和子进程,然后等待子进程向事件发出信号并终止父进程。在创建时,子进程通过OpenEvent() API打开事件对象,调用SetEvent() API使其转化为已接受信号状态。两个进程在发出信号之后几乎立即终止。 步骤1:登录进入Windows 2000 Professional。 步骤2:在“开始”菜单中单击“程序”-“Microsoft Visual Studio 6.0”–“Microsoft Visual C++ 6.0”命令,进入Visual C++窗口。

Windows服务列表

Windows服务列表 在优化Windows xp系统时,需要关闭一些不常用的服务,但是在众多的服务项目中,它们是做什么用的?能关吗?这往往困恼很多新手。这里收集到的这篇关于xp系统服务的详细解读资料,希望对需要优化系统的朋友有所帮助。 1、Alerter Alerter(警示器)服务的进程名是Service.exe(即启动这个服务后在后台运行的进程名称,可以通过任务管理器看到,下同)。Alerter服务的功能是,WinXP将系统上发生的与管理有关的事件以警示(Alert)信息传送至网络上指定的电脑或用户,例如当发生打印错误或硬盘即将写满等事件,这类警示信息由WinXP 的警示器服务(Alerter Service)收集、送出。尽管Alerter依存的服务并没有Messenger(信使)服务,但Alerter服务必须依靠后者才能送出信息,故在启动Alerter服务后还必须确定Messenger服务也在工作状态,而接收的电脑也必须启动Messenger服务。由于Alerter服务运行后,服务是用户可以发送“弹出(Pop-up)”信息给其他用户,这些信息有可能被攻击者用来实施攻击,如诱骗用户修改口令等,从而造成安全隐患。同时该服务使得用户账号泄漏,也有可能被攻击者利用来进行口令猜测攻击。所以对于家庭单机用户,甚至对于绝大多数小型的局域网来说,这个功能是完全可禁用的,不仅节省了系统资源和加快启动速度,也提高了机器的安全性。 2、Application Layer Gateway Service 简称“ALG”(应用层网关)的进程名是alg.exe,WinXP Home/Pro默认安装的启动类型为手动。ALG 又被称为代理服务器(Proxy Server),是网络防火墙从功能层面上分类的一种。当内部计算机与外部主机连接时,将由代理服务器担任内部计算机与外部主机的连接中继者。使用ALG的好处是隐藏内部主机的地址和防止外部不正常的连接,如果代理服务器上未安装针对该应用程序设计的代理程序时,任何属于这个网络服务的封包将无法通过防火墙。通俗点说,具体到ALG本身,它就是附带的Internet连接共享/防火墙的具体控管程序,如果你需要启动这二者,这个服务是必备的。当然,只有一台计算机的上网家庭可以考虑禁用这个服务,不过WinXP内置的防火墙效果还是不错的,如果不是坚持要用第三方的防火墙,还是开着它吧。 3、Application Management AppMent(应用程序管理服务)的进程名是Svchost.exe,WinXP Home/Pro默认安装的启动类型为手动,没有任何依存服务关系。从Win2000开始,微软引入了一种基于MSI文件格式(应用程序安装信息程序包文件)的全新、有效软件管理方案——即应用程序管理组件服务(Application Management),它不仅管理软件的安装、删除,而且可使用此项服务修改、修复现有应用程序,监视文件复原并通过复员排除基本故障等。通常这个服务我们保持其默认状态较好。 可能许多朋友都有印象,当年ACDSee4.0刚发布时,由于安装制作上的考虑不周,并没有考虑到那个时候大多数人的系统还并不支持MSI安装格式,结果只得又去下载安装一个名为Windows Installer的MSI 辅助文件才解决问题。通常以MSI文件格式安装的软件十分好认,比如说Office XP,当你安装后再次运行

Windows多线程程序设计

Windows多线程程序设计- - 1、产生一个线程,只是个框架,没有具体实现。理解::CreateThread函数用法。 #include DWORD WINAPI ThreadFunc(LPVOID); int main() { HANDLE hThread; DWORD dwThreadID; hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(ThreadFunc), NULL, 0, &dwThreadID); ...; return 0; } DWORD WINAPI ThreadFunc(LPVOID lParam) { ...; return 0; } 2、一个真正运转的多线程程序,当你运行它的时候,你会发现(也可能会害怕),自己试试吧。说明了多线程程序是无法预测其行为的,每次运行都会有不同的结果。 #include #include using namespace std; DWORD WINAPI ThreadFunc(LPVOID); int main() { HANDLE hThread; DWORD dwThreadID; // 产生5个线程 for(int i=0; i<5; i++)

{ hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(ThreadFunc), (LPVOID)&i, 0, &dwThreadID); if(dwThreadID) cout << "Thread launched: " << i << endl; } // 必须等待线程结束,以后我们用更好的处理方法 Sleep(5000); return 0; } DWORD WINAPI ThreadFunc(LPVOID lParam) { int n = (int)lParam; for(int i=0; i<3; i++) { cout << n <<","<< n <<","<< n << ","< } return 0; } 3、使用CloseHandle函数来结束线程,应该是“来结束核心对象的”,详细要参见windows 多线程程序设计一书。 修改上面的程序,我们只简单的修改if语句。 if(dwThreadID) { cout << "Thread launched: " << i << endl; CloseHandle(dwThreadID); } 4、GetExitCodeThread函数的用法和用途,它传回的是线程函数的返回值,所以不能用GetExitCodeThread的返回值来判断线程是否结束。 #include #include using namespace std;

WINDOWS 2003 SERVER 进程详解

Windows2003Server进程详解 svchost.exe文件对那些从动态链接库中运行的服务来说是一个普通的主机进程名;最基本的系统进程(也就是说,这些进程是系统运行的基本条件,有了这些进程,系统就能正常运行):smss.exe Session Manager csrss.exe子系统服务器进程winlogon.exe管理用户登录services.exe包含很多系统服务lsass.exe管理IP安全策略以及启动 ISAKMP/Oakley(IKE)和IP安全驱动程序。(系统服务) 产生会话密钥以及授予用于交互式客户/服务器验证的服务凭据(ticket)。(系统服务) svchost.exe包含很多系统服务svchost.exe SPOOLSV.EXE将文件加载到内存中以便迟后打印。(系统服务) explorer.exe资源管理器internat.exe托盘区的拼音图标附加的系统进程(这些进程不是必要的,你可以根据需要通过服务管理器来增加或减少):mstask.exe允许程序在指定时间运行。(系统服务) regsvc.exe允许远程注册表操作。(系统服务) winmgmt.exe提供系统管理信息(系统服务)。 inetinfo.exe通过Internet信息服务的管理单元提供FTP连接和管理。(系统服务)tlntsvr.exe允许远程用户登录到系统并且使用命令行运行控制台程序。(系统服务)允许通过Internet信息服务的管理单元管理Web和FTP服务。(系统服务) tftpd.exe实现TFTP Internet标准。该标准不要求用户名和密码。远程安装服务的一部分。(系统服务) termsrv.exe提供多会话环境允许客户端设备访问虚拟的Windows2000Professional 桌面会话以及运行在服务器上的基于Windows的程序。(系统服务) dns.exe应答对域名系统(DNS)名称的查询和更新请求。(系统服务) 以下服务很少会用到,上面的服务都对安全有害,如果不是必要的应该关掉tcpsvcs.exe

一个多线程的windows控制台应用程序

一个多线程的windows控制台应用程序 一、要求: 编写一个单进程、多线程的windows控制台应用程序。 二、平台: Window XP C# 三、内容: 每个进程都有分配给它的一个或多个线程。线程是一个程序的执行部分。 操作系统把极短的一段时间轮流分配给多个线程。时间段的长度依赖于操作系统和处理器。 每个进程都开始一个默认的线程,但是能从它的线程池中创建一个新的线程。 线程是允许进行并行计算的一个抽象概念:在一个线程完成计算任务的同时,另一个线程可以对图像进行更新,两个线程可同时处理同一个进程发出的两个网络请求。 如图所示,选择操作: 1、创建和启动一个线程。在一个进程中同时教和运行两个线程,并且可以不需要停止或者释放一个线程。 相关代码及其解释: public class Threading1:Object { public static void startup() { //创建一个线程数组 Thread[] threads=new Thread[2]; for(int count=0;count

public static void Count() { for(int count=1;count<=9;count++) Console.Write(count+" "); } } 输出结果: 这里通过new方法创建了两个线程,然后使用start()方法来启动线程,两个线程的作用是:两个线程同时从1数到9,并将结果打印出来。 运行上面的程序代码时,可能会在控制台上输出多种不同的结果。从123456789123456789到112233445566778899或121233445566778989在内的各种情况都是可能出现的,输出结果可能与操作系统的调度方式有关。 2、停止线程。当创建一个线程后,可以通过多种属性方法判断该线程是否处于活动状态,启动和停止一个线程等。相关代码及其解释: public class MyAlpha { //下面创建的方法是在线程启动的时候的时候调用 public void Beta() { while(true) { Console.WriteLine("MyAlpha.Beta is running in its own thread."); } } } public class Simple { public static int Stop() { Console.WriteLine("Thread Start/Stop/Join"); MyAlpha TestAlpha=new MyAlpha(); //创建一个线程对象 Thread MyThread=new Thread(new ThreadStart(TestAlpha.Beta)); //开起一个线程 MyThread.Start(); while(!MyThread.IsAlive);

windows 并发的多线程的应用

(1)苹果香蕉问题 #include using namespace std; #include #include int k; HANDLE Apple_;HANDLE Banana_; CRITICAL_SECTION mmutex; DWORD WINAPI Son(LPVOID n) {//HANDLE Apple_; CRITICAL_SECTION mmutex; int i=1; OpenSemaphore(MUTEX_ALL_ACCESS,false,"Apple_"); while(1) { ::WaitForSingleObject(Apple_,INFINITE);//等苹果 cout<<"Son eats"<

Windows下多线程同步机制

多线程同步机制 Critical section(临界区)用来实现“排他性占有”。适用范围是单一进程的各线程之间。它是: ·一个局部性对象,不是一个核心对象。 ·快速而有效率。 ·不能够同时有一个以上的critical section被等待。 ·无法侦测是否已被某个线程放弃。 Mutex Mutex是一个核心对象,可以在不同的线程之间实现“排他性占有”,甚至几十那些现成分属不同进程。它是: ·一个核心对象。 ·如果拥有mutex的那个线程结束,则会产生一个“abandoned”错误信息。 ·可以使用Wait…()等待一个mutex。 ·可以具名,因此可以被其他进程开启。 ·只能被拥有它的那个线程释放(released)。 Semaphore Semaphore被用来追踪有限的资源。它是: ·一个核心对象。 ·没有拥有者。 ·可以具名,因此可以被其他进程开启。 ·可以被任何一个线程释放(released)。 Ev ent Object Ev ent object通常使用于overlapped I/O,或用来设计某些自定义的同步对象。它是: ·一个核心对象。 ·完全在程序掌控之下。 ·适用于设计新的同步对象。 · “要求苏醒”的请求并不会被储存起来,可能会遗失掉。 ·可以具名,因此可以被其他进程开启。 Interlocked Variable 如果Interlocked…()函数被使用于所谓的spin-lock,那么他们只是一种同步机制。所谓spin-lock是一种busy loop,被预期在极短时间内执行,所以有最小的额外负担(overhead)。系统核心偶尔会使用他们。除此之外,interlocked variables主要用于引用技术。他们:·允许对4字节的数值有些基本的同步操作,不需动用到critical section或mutex之类。 ·在SMP(Symmetric Multi-Processors)操作系统中亦可有效运作。 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

在Windows下创建进程和线程的API

利用API在Windows下创建进程和线程 前言: 谈到在Windows创建线程的例子,在网上的很多的参考都是基于MFC的。其实,就操作系统实验这个前提而言,大可不必去碰那个大型的MFC的框架。在Windows命令控制台下可创建进程及线程,做些简单的进程及线程的测试程序。 1、实验准备: 要实验的Windows下的多线程实验,应做如下准备: a) 在新建中选”Win32 Console Application”的An empty project b) 选”工程”的”设置”选项,在”设置”中选择“C/C++”标签,在”Project Option”中,将”MLd”参数改成“MTd”(如图1)。 图1 选项 以上两步对实验成功至关重要,否则,即是代码无误,在连接时同样会出现问题。 2、Windows下进程的创建: Windows的进程和线程模型被描述成”多进程,基于单进程的多线程”。 在创建一个线程时,Windows会做大量的工作---创建一个新的地址空间,为进程分配资源以及创建一个基线程。

CreateProcess函数的原型如下: 虽然有很多参数,不过在现阶段的实验级别,大多数参数只要用默认值即可。 下面要做的关于Windows使用进程的实验,在Linux系统下,可以使用类似: execve(char* cmdName ,char* cmdArgu)的语句从一个程序中去执行其它的程序。 而如果在Windows下,当使用CreateProcess去执行相应的功能时,只要去改变cmdLine中的容即可,其它的参数使用默认值,具体见代码1: 代码1执行的功能是从命令行中启动这个名叫的launch的测试程序,在launch后面应加上保存有需要打开程序路径的文件名: 如在命令行中键入: >launch set.txt 而set.txt中的容为: C:\\WINDOWS\\SYSTEM32\\CALC.EXE C:\\WINDOWS\\SYSTEM32\\NOTEPAD.EXE NEW.TXT C:\\WINDOWS\\SYSTEM32\\CHARMAP.EXE 路径的前半部分为”C:\\WINDOWS\\”,这当然要视你的Windows系统的类型以及系统盘的存放位置而定。如果是NT或2000的机器,则应使用WINNT. /*测试程序1: 示例如使用进程的launch程序(启动程序),通过在命令行中加载相应的命令文件,去按照命令文件中指定的程序路径打开相应的程序去执行*/

Windows可以停止的服务进程

Windows可以停止的服务进程 2009.8.8 今天实验室多出来一台电脑,刚好在我的桌上,我就脸皮厚下默认确实是给俺分配的了,再也不用每天来回背着笔记本了。但可能由因此公用的电脑,运行的速度可想而知了,桌面上一堆的文件夹,启动项也是电脑上装的软件开机时都会自动启动一遍,任务治理器也是有专门多惊奇的进程。 Windows有专门多不重要的服务进程,这些进程能够停止关闭的,有的进程可能100年也用不到。在运行里直截了当输入services.msc命令能够打开服务选项,右击相关服务进程,属性勾选“已禁用”,即可终止。超级兔子或优化大师也有服务查看停止功能。 能够禁用的系统服务进程(zz) Alerter 微软:通知选取的使用者及运算机系统治理警示。假如停止那个服务,使用系统治理警示的程序将可不能收到通知。假如停用那个服务,所有依存于它的服务将无法启动。 补充:一样家用运算机全然不需要传送或接收运算机系统治理来的警示(Administrative Alerts),除非你的运算机用在局域网络上 依存:Workstation 建议:可禁止 Application Layer Gateway Service 微软:提供因特网联机共享和因特网联机防火墙的第三方通讯协议插件的支持 补充:假如你不使用因特网联机共享(ICS) 提供多台运算机的因特网存取和因特网联机防火墙(ICF) 软件你能够关掉 依存:Internt Connection Firewall (ICF) / Internet Connection Sharing (ICS) 建议:已停用 Application Management (应用程序治理) 微软:提供指派、发行、以及移除的软件安装服务。 补充:如上说的软件安装变更的服务 建议:手动 Automatic 更新 微软:启用重要Windows 更新的下载及安装。假如停用此服务,能够手动的从Windows 更新网站上更新操作系统。 补充:承诺Windows 于背景自动联机之下,到Microsoft Servers 自动检查和下载更新修补程序 建议:已停用 ClipBook (剪贴簿) 微软:启用剪贴簿检视器以储存信息并与远程运算机共享。假如那个服务被停止,剪贴簿检视器将无法与远程运算机共享信息。假如那个服务被停用,任何明确依存于它的服务将无

Windows多线程及消息队列

1.所谓的worker线程,是指完全不牵扯到图形用户界面(GUI),纯粹做运算的线程。 2.微软的多线程模型: Win32说明文件一再强调线程分为GUI线程和worker线程两种。GUI线程负责建造窗口以及处理主消息循环。Worker负责执行纯粹的运算工作,如重新计算或重新编页等,这些运算工作会导致主线程的消息队列失去反应。一般而言,GUI线程绝不会去做那些不能够马上完成的工作。 GUI线程的定义是:拥有消息队列的线程。任何一个特定窗口的消息总是被产生这一窗口的线程抓到并处理。所有对此窗口的改变也都应该由该线程完成。 如果worker线程也产生了一个窗口,那么就会有一个消息队列随之被产生出来并且附着到此线程身上,于是worker线程摇身一变成了GUI线程。这里的意思是:worker线程不能够产生窗口、对话框、消息框,或任何其他与UI有关的东西。 如果一个worker线程需要输入或输出错误信息,它应该授权给UI线程来做,并且将结果通知给worker线程。 消息队列是一个链表,只有在必要的时候,才有元素产生出来。具体的关于消息队列的数据结构,可以参考相关的windows文档。 3.在Win32中,每一个线程有它自己专属的消息队列。这并不意味着每一个窗口有它自己的消息队列,因为一个线程可以产生许多窗口。如果一个线程停止回应,或是它忙于一段耗时的计算工作,那么由它产生的窗口统统都会停止回应,但系统中的其他窗口还会继续正常工作。 以下是一个非常基本的规则,用来管理Win32中的线程、消息、窗口的互动: 所有传送给某一窗口之消息,将由产生该窗口之线程负责处理。 比方说,使用SetWindowText来更新一个Edit框的内容,其实就是发出了一个WM_SETTEXT 消息给edit窗口函数。推而广之,每一个控件都是一个窗口,都拥有自己的窗口函数。 对窗口所作的一切事情基本上都会被该窗口的窗口函数处理,并因此被产生该窗口的线程处理。当需要发送一个消息时,Windows会自动计算出哪一个线程应该接收到消息(以便确定该消息实体应该挂在在哪一个线程的消息队列中)。同时,windows还会确定线程应该如何被告知有这么一个消息进来。一共有四种可能: (1)如果属于同一线程,使用SendMessage传递消息,则直接调用窗口函数。 (2)如果属于同一线程,使用PostMessage传递消息,则把消息放在消息队列中然后立即返回。(3)如果不属于同一线程,使用SendMessage传递消息,则切换到新线程中并调用窗口函数。在该窗口函数结束之前,SendMessage不会返回。 (4)PostMessage立刻返回,消息则被放到另一线程的消息队列中。 当我send一个消息给另一线程掌握的窗口时,系统必须做一次context switch,切换到另一线程去,调用该窗口函数,然后再做一次contex t switch切换回来,相对一般的函数调用而言,期间的额外负担较大。如果在MDI中,为每个子窗口分配一个线程,那么该子窗口的所有资源——包括画刷,DC,调色板等等都属于线程的资源。此时为线程做context switch时会代价很大。

22进程、线程与并行计算(windows 编程技术)

第22章 进程、线程与并行计算 进程是正在运行的程序,线程是轻量级的进程。多任务的并发执行会用到多线程(multithreading ),而CPU 的多核(mult-core )化又将原来只在巨型机和计算机集群中才使用的并行计算带入普通PC 应用的多核程序设计中。 本章先介绍进程与线程的概念和编程,再给出并行计算的基本概念和内容。下一章讨论基于多核CPU 的并行计算的若干具体编程接口和方法。 22.1 进程与线程 进程(process )是执行中的程序,线程(thread )是一种轻量级的进程。 22.1.1 进程与多任务 现代的操作系统都是多任务(multitask )的,即可同时运行多个程序。进程(process )是位于内存中正被CPU 运行的可执行程序实例,参见图22-1。 图22-1 程序与进程 目前的主流计算机采用的都是冯·诺依曼(John von Neumann )体系结构——存储程序计算模型。程序(program )是在内存中顺序存储并以线性模式在CPU 中串行执行的指令序列。对于传统的单核CPU 计算机,多任务操作系统的实现是通过CPU 分时(time-sharing )和程序并发(concurrency )完成的。即在一个时间段内,操作系统将CPU 分配给不同的程序,虽然每一时刻只有一个程序在CPU 中运行,但是由于CPU 的速度非常快,在很短的时间段中可在多个进程间进行多次切换,所以用户的感觉就像多个程序在同时执行,我们称之为多任务的并发。 22.1.2 进程与线程 程序一般包括代码段、数据段和堆栈,对具有GUI (Graphical User Interfaces ,图形用户界面)的程序还包含资源段。进程(process )是应用程序的执行实例,即正在被执行的程进程(内存中) 可执行文件(盘上) 运行

Windows进程与线程数据结构

《操作系统原理实验》 Windows进程与线程数据结构 主讲:黄伯虎

Windows 体系结构 简化的windows 结构图 Kernel: 由低层次的操作系统功能构成,比如线程调度、中断和异常分发、多处理器同步等。提供了一些例程和基本对象。执行体可以利用这些对象实现更高层次的功能。 Executive: 包含了基本的操作系统服务,包括内存管理、进程和线程管理、安全性、I/O 、网络和跨进程通信等。

Windows基本对象暴露给windows API的执行体对象 执行体对象: 指由执行体的各种组件(比如 进程管理器、内存管理器、 I/O子系统等)所实现的对 象。用户可见。 内核对象: 指由Windows内核实现的一 组更为基本的对象。内核对 象对用户而言是不可见的, 只能在执行体内部被创建和 使用。

Windows进程的组成(从最高抽象层次看) 一个私有的虚拟地址空间 一个可执行的程序:定义了代码和数据,并被映射到进程的虚拟地址空间。 一个已经打开句柄的列表:指向各种资源,比如信号量、文件,该进程的所有线程都可访问这些系统资源。 一个被称为访问令牌的安全环境:标识与该进程关联的用户、安全组和特权 一个被称为进程ID的唯一标识 至少一个执行线程

Windows进程的关键数据结构 执行体进程块(EPROCESS) 执行体进程对象的对象体,包括进程ID、父进程ID、程序名、进程优先级、内存管理信息、设备映像等。 核心进程块(KPROCESS) 内核进程对象的对象体,又称PCB,包括线程调度时需要的信息,如进程状态、线程时间片等。 进程环境块(PEB) 包括用户态代码需要和修改的信息。 Windows环境子系统核心态部件win32k.sys为每个进程建立的进程信息数据结构WIN32KPROCESS Windows环境子系统进程csrss(用户态)为每个进程建立的进程信息数据结构

Windows多线程编程_C语言

Windows多线程编程-C语言 先上代码: #include #include// for HANDLE #include// for _beginthread() #include unsigned__stdcall thread(void * i) //子线程入口函数 { int * k = (int *)i; printf("这是子线程%d\n", *k); return 1; // the thread exit code } int main() { HANDLE hth1;//子线程句柄 unsigned Thread1ID;//子线程ID int i = 1;//子线程入口函数参数 //创建子线程 hth1 = (HANDLE)_beginthreadex(NULL, // security,安全属性 0, // stack size thread, //子线程入口函数 &i, // arg list 入口函数参数地址 CREATE_SUSPENDED, //先挂起该线程 &Thread1ID);//线程标识符 if (hth1 == 0)//如果返回的hth1的值为0 则表示创建子线程失败 printf("Failed to create thread 1\n"); DWORD ExitCode; //线程退出码 GetExitCodeThread(hth1, &ExitCode); //获取线程退出码,因为刚刚创建,所以 //肯定还未退出,此时的退出码应为259,表示STILL_ACTIVE printf("initial thread 1 exit code = %u线程未退出\n", ExitCode); ResumeThread(hth1); // 激活线程 WaitForSingleObject(hth1, INFINITE);//等待线程结束 GetExitCodeThread(hth1, &ExitCode);//获取线程退出码 printf("thread 1 exited with code %u,its pid=%u,its handle=%d\n", ExitCode, Thread1ID,hth1);

Windows中线程间同步的方法

Windows中线程间同步的方法主要有:事件(Event)、临界区(Critical Section)、互斥量(Mutex)和信号灯(Semaphore)。 1)使用事件对象进行线程间同步: 在使用CreateEvent函数创建事件对象时,将bManualReset参数设置为FALSE,然后在需要独占操作的代码前面加上一个WaitForSingleObject函数,后面加上一个SetEvent即可。 由于bManualReset参数为FALSE,这样当某个线程等待到Event后,Event对象的状态马上就变为复位状态,这样其他线程执行到WaitForSingleObject时就全部处于等待中了,当活动的线程操作完毕后,执行SetEvent函数,Event对象的状态才恢复到置位,这样其他等待的线程才会有一个能继续操作。 SetEvent函数原型如下: HANDLE WINAPI CreateEvent( __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes, //安全描述符 __in BOOL bManualReset, //指定事件对象是否需要手动复位 __in BOOL bInitialState, //指定事件对象创建时的初始状态,为TRUE表示初始状态是置位状态; //为FALSE表示初始状态是复位状态 __in_opt LPCTSTR lpName //指定事件对象名称 ); 当一个事件被创建后,程序就可以通过SetEvent和ResetEvent函数来设置事件的状态:BOOL WINAPI SetEvent( __in HANDLE hEvent ); BOOL WINAPI ResetEvent(

当前流行的Windows操作系统能同时运行几个程序独立运行

当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力。用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义。现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的。因此掌握多线程多任务设计方法对每个程序员都是必需要掌握的。本实例针对多线程技术在应用中经常遇到的问题,如线程间的通信、同步等,分别进行探讨,并利用多线程技术进行线程之间的通信,实现了数字的简单排序。 一、实现方法 1、理解线程 要讲解线程,不得不说一下进程,进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它系统资源组成。进程在运行时创建的资源随着进程的终止而死亡。线程的基本思想很简单,它是一个独立的执行流,是进程内部的一个独立的执行单元,相当于一个子程序,它对应于Visual C++中的CwinThread类对象。单独一个执行程序运行时,缺省地包含的一个主线程,主线程以函数地址的形式出现,提供程序的启动点,如main ()或WinMain()函数等。当主线程终止时,进程也随之终止。根据实际需要,应用程序可以分解成许多独立执行的线程,每个线程并行的运行在同一进程中。 一个进程中的所有线程都在该进程的虚拟地址空间中,使用该进程的全局变量和系统资源。操作系统给每个线程分配不同的CPU时间片,在某一个时刻,CPU只执行一个时间片内的线程,多个时间片中的相应线程在CPU内轮流执行,由于每个时间片时间很短,所以对用户来说,仿佛各个线程在计算机中是并行处理的。操作系统是根据线程的优先级来安排CPU 的时间,优先级高的线程优先运行,优先级低的线程则继续等待。 线程被分为两种:用户界面线程和工作线程(又称为后台线程)。用户界面线程通常用来处理用户的输入并响应各种事件和消息,其实,应用程序的主执行线程CWinAPP对象就是一个用户界面线程,当应用程序启动时自动创建和启动,同样它的终止也意味着该程序的结束,进程终止。工作线程用来执行程序的后台处理任务,比如计算、调度、对串口的读写操作等,它和用户界面线程的区别是它不用从CWinThread类派生来创建,对它来说最重要的是如何实现工作线程任务的运行控制函数。工作线程和用户界面线程启动时要调用同一个函数的不同版本;最后需要读者明白的是,一个进程中的所有线程共享它们父进程的变量,但同时每个线程可以拥有自己的变量。

Windows环境下的多线程编程

Windows环境下的多线程编程浅讲这是一个简单的关于多线程编程的指南,任何初学者都能在这里找到关于编写简单多线程程序的方法。如果需要更多的关于这方面的知识可以参考MSDN或本文最后列出的参考文献。本文将以C语言作为编程语言,在Lcc-Win32编译器下进行编译调试,使用MS-Visual Studio的人可以参考其相关的使用手册。没有C语言基础的朋友可以找一本简单的教程看一下,相信会是有帮助的。 首先解释什么是线程,谈到这个就不得不说一下什么是进程,这是两个相关的概念。为了方便理解,我推荐大家下载并使用一下flashget(网际快车)这个下载软件,当然迅雷也行,只是不如flashget这么直观了。O.K.言归正传,当我们打开flashget这个软件时,就是启动了一个进程。这个进程就指flashget这个软件的运行状态。当我们用它来下载时都是在整个flashget软件里操作,所以可以把单个进程看作整个程序的最外层。然后我们可以看到,在用flashget下载时可以选择同时使用多少线程来下载的选项(这里介绍个小技巧,用超级兔子可以优化这里的选项,将最大的线程数限制从10改为30),这个选项就包含了我所要讲的线程的概念。当同时用比如5根线程来下载的话,flashget就会同时使用5个独立的下载程序来下载文件(各个线程通过某种方式通信,以确定各自所要下载的部分,关于线程间的通信在后面介绍)。所以线程可以看作是在进程框架下独立运行的与进程功能相关的程序。如果将windows看作进程的话,那么里面跑得QQ啊,MSN什么的都可以看作是windows的线程了。当然进程本身也可以看作是线程,只是凌驾于其它线程之上的线程罢了。另外比如我们使用浩方对战平台来网上对战,当用浩方启动魔兽时,由于运行的是两个不同的程序,那就是多进程编程了,这要比多线程复杂点,但也是复杂的有限,有兴趣的人可以参考MSDN上的相关资料。 最后声明一下,文中的例子都没有过多的注释,不过我都使用了最简单的例子(至少我个人已经想不出更简单的了),如果读者对理解这里的程序上有困难,那么我的建议是这篇文章已经不适合你了,你应该看一些更基础的书,比如《小学生基础算数》^_^。 为了使对多线程编程有个更感性的认识,这里先给出一个简单的多线程程序。

Windows常见进程分析

Windows常见进程分析 向阳 摘要: 进程概念的引入是为了使多个作业并发运行,在操作系统实现了多道程序设计以后为了提高的运行效率,系统允许同时有多个作业驻留内存,并发运算,这样计算机内就存在了竞争。操作系统的进程管理模块,就是为了处理这种竞争而设计的。管理和控制好程序的执行,组织和协调程序对处理机的争夺使用,最大限度地提高处理机的利用率,是计算机进程所需要解决的问题。 关键词:进程、操作系统 一、进程概述 1.进程概念 进程是执行程序的机制,可以理解为程序对数据或请求的处理过程。进程主要有以下几个方面组成:至少一个可执行的程序;一个独立的进程用户空间;系统资源(包括输入输出设备、文件等);一个执行栈区,包含运行现场信息【3】。操作系统相关的进程管理和资源管理模块负责创建进程、为进程加载用户态运行程序、为进程分配资源、调度进程占用处理机、支持进程间通信等。可以把操作系统看成支持进程并且对进程所用系统资源进行管理的系统。 2.进程控制块 为了描述进程的运行变化情况,操作系统为每个进程定义了一个数据结构,叫进程控制块。它包含了进程的描述信息和管理控制信息,是进程动态性的集中体现。进程控制块包含三大类信息:进程标识信息、处理机状态信息、进程控制信息。 3.进程的状态 为了便于管理,进程在从无到有直到完成运行而消亡的整个生命周期内,需要经历状态的转换,按不同的层次分为三态、五态和七态【2】。通常进程主要出于五种状态,即运行状态、就绪状态、阻塞状态、创建状态和结束状态。 4.进程调度 操作系统管理系统的有限资源,当有多个进程要使用这些资源时,鉴于资源的有限性,必须按照一定的原则选择进程来占用资源,即为调度【1】。针对使用者占用不同资源调度有高级调度、中级调度和低级调度。把CPU的调度分为三级有利于提高系统的资源利用率。进程调度通常采用非抢先(或非剥夺)和抢先(剥夺)两种方式。 进程的调度对于有不同设计目的的系统,通常才有不同的算法,以尽可能减少作业进程的优先级调度法等待时间和转换时间,提高系统资源的利用率。处理机调度通常采用以下算法:先来先服务算法、最短作业的进程优先调度法、响应比高者优先调度法、轮转法和多级反馈队列轮转法。 5.线程 为了实现程序之间的并行执行,操作系统围绕进程这个概念进行设计和构造。进程在逻辑上表示操作系统必须做的一个作业,线程表示完成该作业的许多可能的子任务。线程是进程中的一个可执行实体,是被操作系统调度的一个独立单位。一个进程可以有多个线程,多线程共享该进程拥有的所有资源。一个线程也由一个线程控制块描述,它包含系统管理线程所需的全部信息。一般由如下几部分组成:一个唯一的标识符;表示处理机状态和运行现场的一组寄存器;两个用于用户天河和心态调用时进行参数传递的堆栈;一个独立的程序计数器;关联的进程和线程指针。【2】 二、Windous具体进程分析 在Windows操作系统中,打开任务管理器,单击“进程”我们可以看到一系列正在运行的进程。下面选取一些主要进程介绍如下:

相关文档
最新文档