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

上传人:b****5 文档编号:28682429 上传时间:2023-07-19 格式:DOCX 页数:13 大小:245.23KB
下载 相关 举报
在Windows下创建进程和线程的API.docx_第1页
第1页 / 共13页
在Windows下创建进程和线程的API.docx_第2页
第2页 / 共13页
在Windows下创建进程和线程的API.docx_第3页
第3页 / 共13页
在Windows下创建进程和线程的API.docx_第4页
第4页 / 共13页
在Windows下创建进程和线程的API.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

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

《在Windows下创建进程和线程的API.docx》由会员分享,可在线阅读,更多相关《在Windows下创建进程和线程的API.docx(13页珍藏版)》请在冰豆网上搜索。

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

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

利用API在Windows下创建进程和线程

前言:

  谈到在Windows创建线程的例子,在网上的很多的参考都是基于MFC的。

其实,就操作系统实验这个前提而言,大可不必去碰那个大型的MFC的框架。

在Windows命令控制台下可创建进程及线程,做些简单的进程及线程的测试程序。

1、实验准备:

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

  a)在新建中选”Win32ConsoleApplication”的Anemptyproject

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

图1选项

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

2、Windows下进程的创建:

  Windows的进程和线程模型被描述成”多进程,基于单进程的多线程”。

  在创建一个线程时,Windows会做大量的工作---创建一个新的地址空间,为进程分配资源以及创建一个基线程。

 

  CreateProcess函数的原型如下:

CreateProcess(

 LPCTSTRlpApplicationName,

 //pointertonameofexecutablemoudle

 LPTSTRcmdLine,

 //pointertocommandlinestring

 LPSECURITY_ATTRIBUTESlpProcessAttributes,

 //pointertoprocesssecurityattributes

 LPSECURITY_ATTRIBUTESlpThreadAttributes,

 //pointertothereadsecurityattributes

 BOOLbInheritHandle,

 //handleinheritanceflag

 DWORDdwCreationFlag,//variouscreationflags

 LPVOIDlpEnviroment,//Enviromentvariable

 LPCTSTRlpCurrentDirectory,//Child'scurrentdirectory

 LPSTARTUPINFOlpStartupInfo,//pointertoStartupInfo

 LPPROCESS_INFORMATIONlpProcessInformation

 //pointertoPROCESS_INFORMATION

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

下面要做的关于Windows使用进程的实验,在Linux系统下,可以使用类似:

  execve(char*cmdName,char*cmdArgu)的语句从一个程序中去执行其它的程序。

  而如果在Windows下,当使用CreateProcess去执行相应的功能时,只要去改变cmdLine中的容即可,其它的参数使用默认值,具体见代码1:

  代码1执行的功能是从命令行中启动这个名叫的launch的测试程序,在launch后面应加上保存有需要打开程序路径的文件名:

  如在命令行中键入:

>launchset.txt

  而set.txt中的容为:

C:

\\WINDOWS\\SYSTEM32\\CALC.EXE

C:

\\WINDOWS\\SYSTEM32\\NOTEPAD.EXENEW.TXT

C:

\\WINDOWS\\SYSTEM32\\CHARMAP.EXE

  路径的前半部分为”C:

\\WINDOWS\\”,这当然要视你的Windows系统的类型以及系统盘的存放位置而定。

如果是NT或2000的机器,则应使用WINNT.

/*测试程序1:

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

#include

#include

#include

#defineMAX_LINE_LEN80

intmain(intargc,char*argv[])

{

//localvariables

FILE*fid;

charcmdLine[MAX_LINE_LEN];

//CreateProcessparameters

LPSECURITY_ATTRIBUTESprocessA=NULL;//Default

LPSECURITY_ATTRIBUTESthreadA=NULL;//Default

BOOLshareRights=TRUE;//Default

DWORDcreationMask=CREATE_NEW_CONSOLE;//Windowperprocess.

LPVOIDenviroment=NULL;//Default

LPSTRcurDir=NULL;//Default

STARTUPINFOstartInfo;//Result

PROCESS_INFORMATIONprocInfo;//Result

//1.Readthecommandlineparameters

/*

if(argc!

=2)

{

fprintf(stderr,"Usage:

lanch\n");

exit(0);

}

*/

//2.Openafilethatcontainasetofcommands

fid=fopen("set.txt","r");//fid=fopen(argv[1],"r")

//3.Foreverycommandinthelaunchfile

while(fgets(cmdLine,MAX_LINE_LEN,fid)!

=NULL)

{

//Readacommandfromthefile

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

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

//Createanewprocesstoexecutethecommand

ZeroMemory(&startInfo,sizeof(startInfo));

startInfo.cb=sizeof(startInfo);

if(!

CreateProcess(

NULL,//Filenameofexecutable

cmdLine,//commandline

processA,//Processinheritedsecurity

threadA,//Threadinheritedsecurity

shareRights,//Rightspropagation

creationMask,//variouscreationflags

enviroment,//Enviromentvariable

curDir,//Child'scurrentdirectory

&startInfo,

&procInfo

{

fprintf(stderr,"CreatProcessfailedonerror%d\n",GetLastError());

ExitProcess(0);

}

}

//Terminateafterallcommandshavefinished.

return0;

}

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

3、Windows线程的创建及实验:

3.1使用CreateThread在Windows下创建线程:

  在Windows中创建线程可以调用两个函数_beginthreadex和CreateThread两个函数,这里只介绍后者。

  CreateThread函数(在主线程基础上创造新的线程)原型:

HANDLECreateThread

 (LPSECURITY_ATTRIBUTESlpThreadAttributes,//pointertothreadsecurityattributes

  DWORDdwStackSize,//initialthreadstacksize,inbytes

  LPSECURITY_START_ROUTINElpStartAddress,//pointertothreadfunction

  LPVOIDlpParameter,//argumentfornewthread

  DWORDdwCreationFlags,//creationflags

  LPDWORDlpThreadId//pointertoreturnedthreadidentifier

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

  a)第三个参数是一个指向函数的指针,所以应传入的参数应为函数的地址,如&Func的形式.而这个传入的参数,则必须被声明成为:

DWORDWINAPIthreadFunc(LPVOIDthreadArgu);

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

  如:

CreateThread(NULL,0,Func,…)

  具体原因:

我目前认为是系函数前部使用WINAPI所致。

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

  参考:

LPVOID的原型:

typedefvoidfar*LPVOID;

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

typedefstruct

{

intfirstArgu,

longsecArgu,

}myType,*pMyType;

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

  在传入点,使用类似:

pMyTypepMyTpeyArgu;

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

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

intintValue=((pMyType)lpvoid)->firstArgu;

longlongValue=((pMyType)lpvoid)->secArgu;

……

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

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

srand((unsignedint)time(NULL));

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

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

Sleep(sleepTime);

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

/*测试程序2:

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

  命令行输入参数:

testthreadNorunSecs

*/

#include

#include

#include

#include

#include

#defineN5

#defineTypefloat

staticintrunFlag=TRUE;

DWORDWINAPIthreadWork(LPVOIDthreadNo);

intparseArgToInt(char*inNumChar);

TypeeRandom(intupLimit);

typedefstruct

{

 intdata;

}INTEGER;

voidmain(intargc,char*argv[])

{

 unsignedintrunTime;

 inti;

 intthreadNum;

 //intN;

 SYSTEMTIMEnow;

 WORDstopTimeMinute,stopTimeSecond;

 DWORDtargetThreadID;

 //Getcommandlineargument,N

 if(argc!

=3)

 {

  printf("pleaseenter:

NThread\n");

  return;

 }

 threadNum=parseArgToInt(argv[1]);

 runTime=parseArgToInt(argv[2]);

 //Getthetimethethreadsshouldrun,runtime

 //Calculatetimetohalt

 //runTime=60;/*inseconds.*/

 GetSystemTime(&now);

 printf("mthread:

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

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

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

 //FOR1TON

 INTEGER*tmpInt;

 for(i=0;i

 {

  //CREATEANEWTHREADTOEXECUTESIMULATEDWORK;

  //threadWork(i);

  tmpInt=(INTEGER*)malloc(sizeof(INTEGER));

  tmpInt->data=i;

  CreateThread(NULL,0,threadWork,tmpInt,0,&targetThreadID);

  Sleep(100);//Letnewlycreatedthreadrun

 }

 //Cyclewhilechildrenwork...

 while(runFlag)

 {

  GetSystemTime(&now);

  if((now.wMinute>=stopTimeMinute)&&(now.wSecond>=stopTimeSecond))

   runFlag=FALSE;

  Sleep(1000);

 }

 Sleep(5000);

 printf("Programendssuccessfully\n");

}

DWORDWINAPIthreadWork(LPVOIDthreadNo)

{

 //localvariables

 doubley;

 constdoublex=3.14159;

 constdoublee=2.7183;

 inti;

 constintnapTime=1000;//inmilliseconds

 constintbusyTime=400;

 inttNo=((INTEGER*)threadNo)->data;

 intsleepTime;

 DWORDresult=0;

 /*randomasizetherandomnumseeds.*/

 srand((unsignedint)time(NULL));

 while(runFlag)

 {

  //Parameterizedprocessorburstphase

  for(i=0;i

  y=pow(x,e);

  //Parameterizedsleepphase

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

  Sleep(sleepTime);

  printf("IamthreadNo.%d,sleepsec:

%ds\n",tNo,sleepTime);

 }

 //Terminate

 returnresult;

}

intparseArgToInt(char*inNumChar)

{

 intequipData=0,i=0;

 while(inNumChar[i]>='0'&&inNumChar[i]<='9')

 {

  equipData=10*equipData+(inNumChar[i]-48);

  i++;

 }

 returnequipData;

}

TypeeRandom(intupLimit)

{

 TypetmpData;

 do

 {

  tmpData=((Type)rand()/(Type)32767)*(Type)100.0*(Type)upLimit;

 }

 while(tmpData>upLimit);

 returntmpData;

}

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

  这里使用的是让测试线程睡眠100秒,如果用的是让测试进程进入死循环的法,则会很快让系统僵掉。

/*测试程序3:

测试在Windows下最多可创建线程的数目.

*/

DWORDWINAPIthreadWork(LPVOIDthreadNo)

{

 DWORDresult=0;

 while(runFlag)

 {

  Sleep(100000);

 }

 //Terminate

 returnresult;

}

voidmain(intargc,char*argv[])

{

 intcount=0;

 DWORDtargetThreadID;

 

 while(runFlag)

 {

  if(CreateThread(NULL,0,threadWork,NULL,0,&targetThreadID)==NULL)

  {

   runFlag=false;

   break;

  }

  else

   count++;

  printf("%d",count);

 }

 Sleep(5000);

 printf("maxthreadsnum:

%d\n",count);

 printf("Programendssuccessfully\n");

}

  在WindowsXP下(赛扬800MHZ,256M存),在上述式下,测得可创建的最多的线程数目为2030个.

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

  这个程序要实现的是最简单的读者,写者程序,读者将1~10十个数字依次填入临界资源区gData,当且仅当gData被读者消费后,写者才可以写入下一个数.

/*测试程序4:

最简单的一个临界资源的读者,写者程序.

*/

DWORDWINAPIthreadReader(LPVOIDlpvoid)

{

 intreader_Data;

 intbusyTime=10000;

 floattmp;

 inti;

 while(gRunFlag)

 {

  while(stateFlag==WRITER_FLAG)

   for(i=0;i

    tmp=pow(2,10);

    reader_Data=gData;

    printf("readergetsdata:

%d\n",gData);

    stateFlag=WRITER_FLAG;

 }

 printf("readerends\n");

 returnNULL;

}

DWORDWINAPIthreadWriter(LPVOIDlpvoid)

{

 intupTime=((INTEGER*)lpvoid)->mInt;

 intbusyTime=10000;

 floattmp;

 inti;

 while(gRunFlag)

 {

  while(stateFlag==READER_FLAG)

  for(i=0;i

   tmp=pow(2,10);

  gData++;

  printf("writergetsdata:

%d\n",gData);

  if(gData==upTime)

   gRunFlag=false;

  stateFlag=READER_FLAG;

 }

 printf("writerends\n");

 returnNULL;

}

/*Main中的调用*/

……

CreateThread(NULL,0,threadReader,tmpInt,0,&targetThreadID);

CreateThread(NULL,0,threadWriter,tmpInt,0,&targetThreadID);

……

  

3.5几点说明:

3.5.1主调用程序在结束时使用Sleep(5000)的意图在于:

使得由它所产生的子线程可以在主进程结束之前,完成如资源释放一类的工作。

3.5.2在随机线程产生测试程序中:

  之所以采用在每个线程部用

srand((unsignedint)time(NULL));

  去初始化每个线程,是为了使得所有的线程拥有自己的随机数种子,否则,如果是在主调用程序中去初始化随机数种子数,则所有的线程得到的随机数序列都是一样的,将无法产生随机效果。

4、应用及推广:

  采用这种在Windows下利用控制台调用WindowsAPI进行操作系统实验的法,具有代码简洁,观察效果好与实现目标接近等优点。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 哲学历史

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1