dword winapi threadp winapi createthread - 电脑|办公 - 电脑办公-杀毒安全-网络-V3学习网
微商网
 
 
导航:首页 |电脑|办公|正文

dword winapi threadp winapi createthread

时间:2021-05-05 17:38:59
操作系统中生产者消费者问题。(c++) include include include const unsigned short SIZE_OF_BUFFER = 10; 缓冲区长度 unsi
作者:

dword winapi threadp

操作系统中生产者消费者问题。

(c++)

#include #include#include const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度 unsigned short ProductID = 0; //产品号 unsigned short ConsumeID = 0; //将被消耗的产品号 unsigned short in = 0; //产品进缓冲区时的下标 unsigned short out = 0; //产品出缓冲区时的下标 int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列 bool g_continue = true; //控制程序结束 HANDLE g_hMutex; //用于线程间的互斥 HANDLE g_hFullItems; //缓冲区中被占用的项 HANDLE g_hEmptyItems; //缓冲区中的空项 DWORD WINAPI Producer(LPVOID); //生产者线程,dword 变量类型的内存占位 DWORD WINAPI Consumer(LPVOID); //消费者线程 int main() { //创建各个互斥信号 g_hMutex = CreateMutex(NULL,FALSE,NULL); g_hFullItems = CreateSemaphore(NULL,0,SIZE_OF_BUFFER,NULL);//创建信号灯,createsemaphore常常被用作多线程同步 g_hEmptyItems = CreateSemaphore(NULL,SIZE_OF_BUFFER, SIZE_OF_BUFFER,NULL); //缓冲区初始化 for (int i = 0; i g_buffer[i] = -1; //当值为-1时该项为空 } const unsigned short PRODUCERS_COUNT =3; //生产者的个数 const unsigned short CONSUMERS_COUNT =2; //消费者的个数 //总的线程数 const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT; HANDLE hThreads[THREADS_COUNT]; //各线程的handle DWORD producerID[PRODUCERS_COUNT]; //生产者线程的标识符 DWORD consumerID[CONSUMERS_COUNT]; //消费者线程的标识符 //创建生产者线程 for ( i=0;i hThreads[i] =CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);//CreateThread是window提供的API函数 if (hThreads[i]==NULL) return -1; //用此函数可创建一个线程 } //创建消费者线程 for (i=0;i hThreads[PRODUCERS_COUNT+i] =CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]); if (hThreads[i]==NULL) return -1; } while(g_continue){ if(getchar()){ //按回车后终止程序运行 g_continue = false; } } return 0; } //生产一个产品。

简单模拟了一下,仅输出新产品的ID号 void Produce() { cout cout } //把新生产的产品放入缓冲区 void Append() { cout g_buffer[in] = ProductID; in = (in+1)%SIZE_OF_BUFFER; cout //输出缓冲区当前的状态 for (int i=0;i cout if (g_buffer[i]==-1) cout else cout if (i==in) cout if (i==out) cout cout } } //从缓冲区中取出一个产品 void Take() { cout ConsumeID = g_buffer[out]; g_buffer[out]= -1; out = (out+1)%SIZE_OF_BUFFER; cout //输出缓冲区当前的状态 for (int i=0;i cout if (g_buffer[i]==-1) cout else cout if (i==in) cout if (i==out) cout cout } } //消耗一个产品 void Consume() { cout cout } //生产者 DWORD WINAPI Producer(LPVOID lpPara) { while(g_continue){ int i=rand()%5; Sleep(i*1000); WaitForSingleObject(g_hEmptyItems,INFINITE);//等待信号灯 WaitForSingleObject(g_hMutex,INFINITE); Produce(); Append(); ReleaseMutex(g_hMutex); ReleaseSemaphore(g_hFullItems,1,NULL); } return 0; } //消费者 DWORD WINAPI Consumer(LPVOID lpPara) { while(g_continue){ int i=rand()%5; Sleep(i*1000);//该线程释放当前的控制权1500毫秒,让系统调度其他线程 WaitForSingleObject(g_hFullItems,INFINITE); WaitForSingleObject(g_hMutex,INFINITE); Take(); Consume(); ReleaseMutex(g_hMutex); ReleaseSemaphore(g_hEmptyItems,1,NULL); } return 0; }

用C语言实现PV操作生产者消费者关系

#include #include typedef HANDLE Semaphore; // 信号量的Windows原型 #define P(S) WaitForSingleObject(S, INFINITE) // 定义Windows下的P操作 #define V(S) ReleaseSemaphore(S, 1, NULL) // 定义Windows下的V操作 #define rate 1000 #define CONSUMER_NUM 10 /* 消费者个数 */ #define PRODUCER_NUM 10 /* 生产者个数 */ #define BUFFER_NUM 4 /* 缓冲区个数 */ char *thing[10] = ; struct Buffer { int product[BUFFER_NUM]; // 缓冲区 int start, end; // 两个指针 } g_buf; Semaphore g_semBuffer, g_semProduct, g_mutex; // 消费者线程 DWORD WINAPI Consumer(LPVOID para) { // i表示第i个消费者 int i = *(int *)para; int ptr; // 待消费的内容的指针 printf(" 猪头-%03d: 猪头我来啦!\n", i); Sleep(300); while (1) { printf(" 猪头-%03d: 我要吃.........!\n", i); // 等待产品 P(g_semProduct); // 有产品,先锁住缓冲区 g_buf P(g_mutex); // 记录消费的物品 ptr = g_buf.start; // 再移动缓冲区指针 g_buf.start = (g_buf.start+1)%BUFFER_NUM; // 让其他消费者或生产者使用 g_buf V(g_mutex); printf(" 猪头-%03d: 我吃 buf[%d] = %s\n", i, ptr, thing[g_buf.product[ptr]]); Sleep(rate*rand()%10+110); // 消费完毕,并释放一个缓冲 printf(" 猪头-%03d: 我爽了! buf[%d] = %s\n", i, ptr, thing[g_buf.product[ptr]]); V(g_semBuffer); } return 0; } // 生产者线程 DWORD WINAPI Producer(LPVOID para) { int i = *(int *)para - CONSUMER_NUM; int ptr; int data; // 产品 printf("工作狂-%03d: 我来啦!\n", i); Sleep(300); while (1) { printf("工作狂-%03d: 我干干干…………\n", i); Sleep(rate*rand()%10+110); data = rand()%10; printf("工作狂-%03d: 搞出一个东西 data = %s!\n", i, thing[data]); // 等待存放空间 P(g_semBuffer); // 有地方,先锁住缓冲区 g_buf P(g_mutex); // 记录消费的物品 ptr = g_buf.end; // 再移动缓冲区指针 g_buf.end = (g_buf.end+1)%BUFFER_NUM; // 让其他消费者或生产者使用 g_buf V(g_mutex); printf("工作狂-%03d: 搁到 buf[%d] = %s\n", i, ptr, thing[data]); g_buf.product[ptr] = data; Sleep(rate/2*rand()%10+110); // 放好了完毕,释放一个产品 printf("工作狂-%03d: buf[%d] = %s 放好了,大家吃!\n", i, ptr, thing[g_buf.product[ptr]]); V(g_semProduct); } return 0; } int main(int argc, char *argv[]) { // 线程技术,前面为消费者线程,后面为生产者线程 HANDLE hThread[CONSUMER_NUM+PRODUCER_NUM]; // 线程计数 //srand(time()); DWORD tid; int i=0; // 初始化信号量 g_mutex = CreateSemaphore(NULL, BUFFER_NUM, BUFFER_NUM, "mutexOfConsumerAndProducer"); g_semBuffer = CreateSemaphore(NULL, BUFFER_NUM, BUFFER_NUM, "BufferSemaphone"); g_semProduct = CreateSemaphore(NULL, 0, BUFFER_NUM, "ProductSemaphone"); if ( !g_semBuffer || !g_semProduct || !g_mutex) { printf("Create Semaphone Error!\n"); return -1; } int totalThreads = CONSUMER_NUM+PRODUCER_NUM; // 开启消费者线程 printf("先请猪头们上席!\n"); for (i=0; i { hThread[i] = CreateThread(NULL, 0, Consumer, &i, 0, &tid); if ( hThread[i] ) WaitForSingleObject(hThread[i], 10); } printf("厨子们就位!\n"); for (; i { hThread[i] = CreateThread(NULL, 0, Producer, &i, 0, &tid); if ( hThread[i] ) WaitForSingleObject(hThread[i], 10); } // 生产者和消费者的执行 WaitForMultipleObjects(totalThreads, hThread, TRUE, INFINITE); return 0; }

VB读取进程内存问题

虽然楼主已经有答案了,但还是科普一下,哈哈!在WIN32中,每个应用程序都可“看见”4GB的线性地址空间,其中最开始的4MB和最后的2GB由操作系统保留,剩下不足2GB的空间用于应用程序私有空间。

具体分配如下:0xFFFFFFFF-0xC0000000的1GB用于VxD、存储器管理和文件系统;0xBFFFFFFF-0x80000000的1GB用于共享的WIN32 DLL、存储器映射文件和共享存储区;0x7FFFFFFF-0x00400000为每个进程的WIN32专用地址;0x003FFFFF-0x00001000为MS-DOS 和 WIN16应用程序;0x00000FFF-0x00000000为防止使用空指针的4,096字节。

以上都是指逻辑地址,也就是虚拟内存。

虚拟内存通常是由固定大小的块来实现的,在WIN32中这些块称为“页”,每页大小为4,096字节。

在Intel CPU结构中,通过在一个控制寄存器中设置一位来启用分页。

启用分页时CPU并不能直接访问内存,对每个地址要经过一个映射进程,通过一系列称作“页表”的查找表把虚拟内存地址映射成实际内存地址。

通过使用硬件地址映射和页表WIN32可使虚拟内存即有好的性能而且还提供保护。

利用处理器的页映射能力,操作系统为每个进程提供独立的从逻辑地址到物理地址的映射,使每个进程的地址空间对另一个进程完全不可见。

WIN32中也提供了一些访问进程内存空间的函数,但使用时要谨慎,一不小心就有可能破坏被访问的进程。

本文介绍如何读另一个进程的内存,写内存与之相似,完善一下你也可以做个 FPE 之类的内存修改工具。

好吧,先准备好编程利器Delphi 和 参考手册 MSDN ,Now begin! ReadProcessMemory 读另一个进程的内存,原形如下: BOOL ReadProcessMemory( HANDLE hProcess, // 被读取进程的句柄; LPCVOID lpBaseAddress, // 读的起始地址; LPVOID lpBuffer, // 存放读取数据缓冲区; DWORD nSize, // 一次读取的字节数; LPDWORD lpNumberOfBytesRead // 实际读取的字节数; ); hProcess 进程句柄可由OpenProcess 函数得到,原形如下: HANDLE OpenProcess( DWORD dwDesiredAccess, // 访问标志; BOOL bInheritHandle, // 继承标志; DWORD dwProcessId // 进程ID; ); 当然,用完别忘了用 CloseHandle 关闭打开的句柄。

读另一个进程的内存 dwDesiredAccess 须指定为 PROCESS_VM_READ ,写另一个进程的内存 dwDesiredAccess 须指定为 PROCESS_VM_WRITE ,继承标志无所谓,进程ID可由 Process32First 和 Process32Next 得到,这两个函数可以枚举出所有开启的进程,这样进程的信息也就得到了。

Process32First 和 Process32Next是由 TLHelp32 单元提供的,需在 uses 里加上TLHelp32。

ToolsHelp32 封装了一些访问堆、线程、进程等的函数,只适用于Win9x,原形如下: BOOL WINAPI Process32First( HANDLE hSnapshot // 由 CreateToolhelp32Snapshot 返回 的系统快照句柄; LPPROCESSENTRY32 lppe // 指向一个 PROCESSENTRY32 结构; ); BOOL WINAPI Process32Next( HANDLE hSnapshot // 由 CreateToolhelp32Snapshot 返回 的系统快照句柄; LPPROCESSENTRY32 lppe // 指向一个 PROCESSENTRY32 结构; ); hSnapshot 由 CreateToolhelp32Snapshot 返回的系统快照句柄; CreateToolhelp32Snapshot 原形如下: HANDLE WINAPI CreateToolhelp32Snapshot( DWORD dwFlags, // 快照标志; DWORD th32ProcessID // 进程ID; ); 现在需要的是进程的信息,所以将 dwFlags 指定为 TH32CS_SNAPPROCESS, th32ProcessID 忽略;PROCESSENTRY32 结构如下: typedef struct tagPROCESSENTRY32 { DWORD dwSize; // 结构大小; DWORD cntUsage; // 此进程的引用计数; DWORD th32ProcessID; // 进程ID; DWORD th32DefaultHeapID; // 进程默认堆ID; DWORD th32ModuleID; // 进程模块ID; DWORD cntThreads; // 此进程开启的线程计数; DWORD th32ParentProcessID;// 父进程ID; LONG pcPriClassBase; // 线程优先权; DWORD dwFlags; // 保留; char szExeFile[MAX_PATH]; // 进程全名; } PROCESSENTRY32; 至此,所用到的主要函数已介绍完,实现读内存只要从下到上依次调用上述函数即可,具体参见原代码: procedure TForm1.Button1Click(Sender: TObject); var FSnapshotHandle:THandle; FProcessEntry32:TProcessEntry32; Ret : BOOL; ProcessID : integer; ProcessHndle : THandle; lpBuffer:pByte; nSize: DWORD; lpNumberOfBytesRead: DWORD; i:integer; s:string; begin FSnapshotHandle:=CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS,0); //创建系统快照 FProcessEntry32.dwSize:=Sizeof(FProcessEntry32); //先初始化 FProcessEntry32 的大小 Ret:=Process32First(FSnapshotHandle,FProcessEntry32); while Ret do begin s:=ExtractFileName(FProcessEntry32.szExeFile); if s="KERNEL32.DLL" then begin ProcessID:=FProcessEntry32.th32ProcessID; s:="; break; end; Ret:=Process32Next(...

如何访问一个进程中的内存

/// 读的起始地址;LPVOID lpBuffer, /// 进程ID;);---- 当然,用完别忘了用 CloseHandle 关闭打开的句柄,只适用于Win9x;LPDWORD lpNumberOfBytesRead //,其中最开始的4MB和最后的2GB由操作系统保留。

---- 虚拟内存通常是由固定大小的块来实现的; //,这两个函数可以枚举出所有开启的进程; 实际读取的字节数:0xFFFFFFFF-0xC0000000的1GB用于VxD、存储器管理和文件系统; /,原形如下:BOOL WINAPI Process32First(HANDLE hSnapshot // /,先准备好编程利器Delphi 和参考手 册 MSDN ;DWORD th32ProcessID。

读另一个进程的内存 dwDesiredAccess 须指定为 PROCESS_VM_READ ,原形如下:HANDLE OpenProcess(DWORD dwDesiredAccess;由 CreateToolhelp32Snapshot 返回的系统快照句柄;LPPROCESSENTRY32 lppe /,剩下不足2GB的空间用于应用程序私有空间。

具体分配如下,也就是虚拟内存; 继承标志;/ 进程全名;} PROCESSENTRY32;0x7FFFFFFF-0x00400000为每个进程的WIN32专用地址;0x003FFFFF-0x00001000为MS-DOS 和 WIN16应用程序;0xBFFFFFFF-0x80000000的1GB用于共享的WIN32 DLL; 进程ID,在WIN32中这些块称为“页”,对每个地址要经过一个映射进程,通过一系列称作“页表”的查找表把虚拟内存地址映射成实际内存地址。

通过使用硬件地址映射和页表WIN32可使虚拟内存即有好的性能而且还提供保护。

利用处理器的页映射能力,操作系统为每个进程提供独立的从逻辑地址到物理地址的映射,使每个进程的地址空间对另一个进程完全不可见。

WIN32中也提供了一些访问进程内存空间的函数,但使用时要谨慎,一不小心就有可能破坏被访问的进程,原形如下:BOOL ReadProcessMemory(HANDLE hProcess;hProcess 进程句柄可由OpenProcess 函数得到,Now begin; 此进程的引用计数。

启用分页时CPU并不能直接访问内存;/ 指向一个 PROCESSENTRY32 结构;);hSnapshot 由 CreateToolhelp32Snapshot 返回的系统快照句柄。

本文介绍如何读另一个进程的内存;/ 父进程ID:HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, /,每页大小为4,096字节。

在Intel CPU结构中,通过在一个控制寄存器中设置一位来启用分页;PROCESSENTRY32 结构如下, /;CreateToolhelp32Snapshot 原形如下; 结构大小。

以上都是指逻辑地址、存储器映射文件和共享存储区;/ 快照标志;DWORD th32ProcessID // 进程模块ID;DWORD cntThreads;/ 进程ID;);现在需要的是进程的信息,所以将 dwFlags指定为 TH32CS_SNAPPROCESS,th32ProcessID 忽略; 线程优先权;DWORD dwFlags; /。

ToolsHelp32 封装了一些访问堆、线程;LONG pcPriClassBase; //;0x00000FFF-0x00000000为防止使用空指针的4;---- 至此,完善一下你也可以做个 FPE 之类的内存修改工具。

好吧,需在 uses 里加上TLHelp32; 一次读取的字节数;DWORD th32DefaultHeapID,写另一个进程的内存 dwDesiredAccess 须指定为 PROCESS_VM_WRITE ,继承标志无所谓,进程ID可由 Process32First 和 Process32Next 得到,096字节;DWORD cntUsage; // 存放读取数据缓冲区;DWORD nSize, // 进程默认堆ID;DWORD th32ModuleID;),写内存与之相似、进程等 的函数; /:typedef struct tagPROCESSENTRY32 {DWORD dwSize; /// 保留;char szExeFile[MAX_PATH];varFSnapshotHandle:THandle;FProcessEntry32:TProcessEntry32;Ret : BOOL;ProcessID : integer;ProcessHndle : THandle;lpBuffer:pByte;nSize: DWORD;lpNumberOfBytesRead: DWORD;i:integer;s:string;beginFSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//创建系统快照FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);//先初始化 FProcessEntry32 的大小Ret:=Process32First(FSnapshotHandle,FProcessEntry32);while Ret dobegins:=ExtractFileName(FProcessEntry32.szExeFile);if s="KERNEL32.DLL" thenbeginProcessID:=FProcessEntry32.th32ProcessID;s:="";break;end;Ret:=Process32Next(FSnapshotHandle,FProcessEntry32);end;//循环枚举出系统开启的所有进程,找出“Kernel32.dll”CloseHandle(FSnapshotHandle);Memo1.Lines.Clear ;memo1.lines.add("Process ID "+IntToHex(FProcessEntry32.th32ProcessID,8));memo1.lines.Add("File name "+FProcessEntry32.szExeFile);////输出进程的一些信息nSize:=4;lpBuffer:=AllocMem(nSize);ProcessHndle:=OpenProcess(PROCESS_VM_READ,false,ProcessID);memo1.Lines.Add ("Process Handle "+intTohex(ProcessHndle,8));for i:=$00800001 to $0080005f dobeginReadProcessMemory(ProcessHndle,Pointer(i),lpBuffer,nSize,lpNumberOfBytesRead);s:=s+intTohex(lpBuffer^,2)+" ";//读取内容if (i mod 16) =0 thenbeginMemo1.Lines.Add(s);s:="";end;//格式化输出end;FreeMem(lpBuffer,nSize);CloseHandle(ProcessHndle);//关闭句柄,释放内存end;;/ 访问标志;...

C++多线程 信号量问题, 如下:

if(NULL == (hSemaphore = OpenSemaphore(SEMAPHORE_MODIFY_STATE , FALSE, strSemaphoreName))){printf("打开信号量对象失败 , 错误ID:%u\n", GetLastError());return;}这几行删掉,你已经在主线程Create一个信号量了,就不需要重复Open了,建议仔细看看msdn。

大家还关注
    
阅读排行
推荐阅读