64,652
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <process.h>
#include <time.h>
#define MIN(_x,_y) ((_x) < (_y)) ? (_x) : (_y)
//设置控制台输出颜色
BOOL SetConsoleColor(WORD wAttributes)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE)
return FALSE;
return SetConsoleTextAttribute(hConsole, wAttributes);
}
volatile int count;
volatile int molecules_left;
int NUM;
CRITICAL_SECTION g_cs;
//HANDLE g_hEventHatomEmpty, g_hEventHatomFull;
HANDLE g_hEventOatomFull,g_hEventOatomEmpty;
HANDLE g_hSemaphoreHEmpty, g_hSemaphoreHFull;
unsigned int __stdcall H_atomThread(PVOID pM)
{
int Hcount = 0;
WaitForSingleObject(g_hSemaphoreHEmpty, INFINITE);
EnterCriticalSection(&g_cs);
printf("线程编号%d的H原子已经从缓冲池中被取出来!\n",GetCurrentThreadId());
Hcount++;
LeaveCriticalSection(&g_cs);
//告诉water线程H原子已到位
ReleaseSemaphore(g_hSemaphoreHFull, 1, NULL);
return 0;
}
unsigned int __stdcall O_atomThreadFun(PVOID pM)
{
WaitForSingleObject(g_hEventOatomEmpty, INFINITE);
EnterCriticalSection(&g_cs);
printf("线程编号%d的O原子已经从缓冲池中被取出来!\n",GetCurrentThreadId());
LeaveCriticalSection(&g_cs);
//告诉water线程O原子已到位
SetEvent(g_hEventOatomFull);
return 0;
}
unsigned int __stdcall WaterThreadFun(PVOID pM)
{
WaitForSingleObject(g_hSemaphoreHFull, INFINITE);
WaitForSingleObject(g_hSemaphoreHFull, INFINITE);
WaitForSingleObject(g_hEventOatomFull, INFINITE);
EnterCriticalSection(&g_cs);
count++;
SetConsoleColor(FOREGROUND_GREEN);
printf("2个H原子与1个O原子已经结合成1个水分子!共合成%d个水分子\n",count);
SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
//告诉生产者 H,O原子已经消耗完毕
if (molecules_left-count>0)
{
printf("1%d\n", molecules_left);
SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
SetEvent(g_hEventOatomEmpty);
ReleaseSemaphore(g_hSemaphoreHEmpty, 2, NULL);
}
else
{
printf("水分子已经全部结合完成,没有多余的元素继续合成!!\n");
SetConsoleColor(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
LeaveCriticalSection(&g_cs);
return 0;
}
int main()
{
//初始化关键段
int total_atoms = 300;
int H_atoms, O_atoms, expected_molecules;
srand((unsigned)time(0)); //改变随机种子
H_atoms = rand() % 150+80;
O_atoms = total_atoms - H_atoms;
expected_molecules = MIN(H_atoms / 2, O_atoms);
molecules_left = expected_molecules;
printf("共有%d个H元素,%d个O元素,预计能合成%d个水分子!\n", H_atoms, O_atoms, expected_molecules);
InitializeCriticalSection(&g_cs);
//自动置位,初始已触发
g_hEventHatomEmpty = CreateEvent(NULL, TRUE, TRUE, NULL);
g_hEventHatomFull = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hEventOatomEmpty = CreateEvent(NULL, FALSE, TRUE, NULL);
g_hEventOatomFull = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hSemaphoreHEmpty = CreateSemaphore(NULL, 2, 2, NULL);
g_hSemaphoreHFull = CreateSemaphore(NULL, 0, 2, NULL);
NUM = O_atoms + H_atoms;
HANDLE hThread[350];
for (int i = 0; i < H_atoms; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, H_atomThread, NULL, 0, NULL);
}
for (int j = H_atoms; j < NUM; j++)
{
hThread[j] = (HANDLE)_beginthreadex(NULL, 0, O_atomThreadFun, NULL, 0, NULL);
}
hThread[NUM] = (HANDLE)_beginthreadex(NULL, 0, WaterThreadFun, NULL, 0, NULL);
WaitForMultipleObjects(NUM+1, hThread, TRUE, INFINITE);
for (int i = 0; i < NUM+1; i++)
CloseHandle(hThread[i]);
//摧毁事件与关键段
//CloseHandle(g_hEventHatomEmpty);
//CloseHandle(g_hEventHatomFull);
CloseHandle(g_hEventOatomEmpty);
CloseHandle(g_hEventOatomFull);
CloseHandle(g_hSemaphoreHEmpty);
CloseHandle(g_hSemaphoreHFull);
DeleteCriticalSection(&g_cs);
return 0;
}
//循环向a函数每次发送200个字节长度(这个是固定的)的buffer,
//a函数中需要将循环传进来的buffer,组成240字节(也是固定的)的新buffer进行处理,
//在处理的时候每次从新buffer中取两个字节打印
#ifdef WIN32
#pragma warning(disable:4996)
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#include <process.h>
#include <io.h>
#define MYVOID void
#define vsnprintf _vsnprintf
#else
#include <unistd.h>
#include <sys/time.h>
#include <pthread.h>
#define CRITICAL_SECTION pthread_mutex_t
#define MYVOID void *
#endif
//Log{
#define MAXLOGSIZE 20000000
#define MAXLINSIZE 16000
#include <time.h>
#include <sys/timeb.h>
#include <stdarg.h>
char logfilename1[]="MyLog1.log";
char logfilename2[]="MyLog2.log";
static char logstr[MAXLINSIZE+1];
char datestr[16];
char timestr[16];
char mss[4];
CRITICAL_SECTION cs_log;
FILE *flog;
#ifdef WIN32
void Lock(CRITICAL_SECTION *l) {
EnterCriticalSection(l);
}
void Unlock(CRITICAL_SECTION *l) {
LeaveCriticalSection(l);
}
void sleep_ms(int ms) {
Sleep(ms);
}
#else
void Lock(CRITICAL_SECTION *l) {
pthread_mutex_lock(l);
}
void Unlock(CRITICAL_SECTION *l) {
pthread_mutex_unlock(l);
}
void sleep_ms(int ms) {
usleep(ms*1000);
}
#endif
void LogV(const char *pszFmt,va_list argp) {
struct tm *now;
struct timeb tb;
if (NULL==pszFmt||0==pszFmt[0]) return;
vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);
ftime(&tb);
now=localtime(&tb.time);
sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);
sprintf(timestr,"%02d:%02d:%02d",now->tm_hour ,now->tm_min ,now->tm_sec );
sprintf(mss,"%03d",tb.millitm);
printf("%s %s.%s %s",datestr,timestr,mss,logstr);
flog=fopen(logfilename1,"a");
if (NULL!=flog) {
fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);
if (ftell(flog)>MAXLOGSIZE) {
fclose(flog);
if (rename(logfilename1,logfilename2)) {
remove(logfilename2);
rename(logfilename1,logfilename2);
}
} else {
fclose(flog);
}
}
}
void Log(const char *pszFmt,...) {
va_list argp;
Lock(&cs_log);
va_start(argp,pszFmt);
LogV(pszFmt,argp);
va_end(argp);
Unlock(&cs_log);
}
//Log}
#define ASIZE 200
#define BSIZE 240
#define CSIZE 2
char Abuf[ASIZE];
char Cbuf[CSIZE];
CRITICAL_SECTION cs_HEX ;
CRITICAL_SECTION cs_BBB ;
struct FIFO_BUFFER {
int head;
int tail;
int size;
char data[BSIZE];
} BBB;
int No_Loop=0;
void HexDump(int cn,char *buf,int len) {
int i,j,k;
char binstr[80];
Lock(&cs_HEX);
for (i=0;i<len;i++) {
if (0==(i%16)) {
sprintf(binstr,"%03d %04x -",cn,i);
sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
} else if (15==(i%16)) {
sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
sprintf(binstr,"%s ",binstr);
for (j=i-15;j<=i;j++) {
sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
}
Log("%s\n",binstr);
} else {
sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
}
}
if (0!=(i%16)) {
k=16-(i%16);
for (j=0;j<k;j++) {
sprintf(binstr,"%s ",binstr);
}
sprintf(binstr,"%s ",binstr);
k=16-k;
for (j=i-k;j<i;j++) {
sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
}
Log("%s\n",binstr);
}
Unlock(&cs_HEX);
}
int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {
int lent,len1,len2;
lent=0;
Lock(cs);
if (fbuf->size>=len) {
lent=len;
if (fbuf->head+lent>BSIZE) {
len1=BSIZE-fbuf->head;
memcpy(buf ,fbuf->data+fbuf->head,len1);
len2=lent-len1;
memcpy(buf+len1,fbuf->data ,len2);
fbuf->head=len2;
} else {
memcpy(buf ,fbuf->data+fbuf->head,lent);
fbuf->head+=lent;
}
fbuf->size-=lent;
}
Unlock(cs);
return lent;
}
MYVOID thdB(void *pcn) {
char *recv_buf;
int recv_nbytes;
int cn;
int wc;
int pb;
cn=(int)pcn;
Log("%03d thdB thread begin...\n",cn);
while (1) {
sleep_ms(10);
recv_buf=(char *)Cbuf;
recv_nbytes=CSIZE;
wc=0;
while (1) {
pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);
if (pb) {
Log("%03d recv %d bytes\n",cn,pb);
HexDump(cn,recv_buf,pb);
sleep_ms(1);
} else {
sleep_ms(1000);
}
if (No_Loop) break;//
wc++;
if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
}
if (No_Loop) break;//
}
#ifndef WIN32
pthread_exit(NULL);
#endif
}
int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {
int lent,len1,len2;
Lock(cs);
lent=len;
if (fbuf->size+lent>BSIZE) {
lent=BSIZE-fbuf->size;
}
if (fbuf->tail+lent>BSIZE) {
len1=BSIZE-fbuf->tail;
memcpy(fbuf->data+fbuf->tail,buf ,len1);
len2=lent-len1;
memcpy(fbuf->data ,buf+len1,len2);
fbuf->tail=len2;
} else {
memcpy(fbuf->data+fbuf->tail,buf ,lent);
fbuf->tail+=lent;
}
fbuf->size+=lent;
Unlock(cs);
return lent;
}
MYVOID thdA(void *pcn) {
char *send_buf;
int send_nbytes;
int cn;
int wc;
int a;
int pa;
cn=(int)pcn;
Log("%03d thdA thread begin...\n",cn);
a=0;
while (1) {
sleep_ms(100);
memset(Abuf,a,ASIZE);
a=(a+1)%256;
if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop
send_buf=(char *)Abuf;
send_nbytes=ASIZE;
Log("%03d sending %d bytes\n",cn,send_nbytes);
HexDump(cn,send_buf,send_nbytes);
wc=0;
while (1) {
pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);
Log("%03d sent %d bytes\n",cn,pa);
HexDump(cn,send_buf,pa);
send_buf+=pa;
send_nbytes-=pa;
if (send_nbytes<=0) break;//
sleep_ms(1000);
if (No_Loop) break;//
wc++;
if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);
}
if (No_Loop) break;//
}
#ifndef WIN32
pthread_exit(NULL);
#endif
}
int main() {
#ifdef WIN32
InitializeCriticalSection(&cs_log);
InitializeCriticalSection(&cs_HEX );
InitializeCriticalSection(&cs_BBB );
#else
pthread_t threads[2];
int threadsN;
int rc;
pthread_mutex_init(&cs_log,NULL);
pthread_mutex_init(&cs_HEX,NULL);
pthread_mutex_init(&cs_BBB,NULL);
#endif
Log("Start===========================================================\n");
BBB.head=0;
BBB.tail=0;
BBB.size=0;
#ifdef WIN32
_beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);
_beginthread((void(__cdecl *)(void *))thdB,0,(void *)2);
#else
threadsN=0;
rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);
#endif
if (!access("No_Loop",0)) {
remove("No_Loop");
if (!access("No_Loop",0)) {
No_Loop=1;
}
}
while (1) {
sleep_ms(1000);
if (No_Loop) break;//
if (!access("No_Loop",0)) {
No_Loop=1;
}
}
sleep_ms(3000);
Log("End=============================================================\n");
#ifdef WIN32
DeleteCriticalSection(&cs_BBB );
DeleteCriticalSection(&cs_HEX );
DeleteCriticalSection(&cs_log);
#else
pthread_mutex_destroy(&cs_BBB);
pthread_mutex_destroy(&cs_HEX);
pthread_mutex_destroy(&cs_log);
#endif
return 0;
}
《Windows核心编程》
Synchronization Functions
The following functions are used in synchronization.
CancelWaitableTimer
CreateEvent
CreateMutex
CreateSemaphore
CreateWaitableTimer
DeleteCriticalSection
EnterCriticalSection
GetOverlappedResult
InitializeCriticalSection
InitializeCriticalSectionAndSpinCount
InterlockedCompareExchange
InterlockedDecrement
InterlockedExchange
InterlockedExchangeAdd
InterlockedIncrement
LeaveCriticalSection
MsgWaitForMultipleObjects
MsgWaitForMultipleObjectsEx
OpenEvent
OpenMutex
OpenSemaphore
OpenWaitableTimer
PulseEvent
QueueUserAPC
ReleaseMutex
ReleaseSemaphore
ResetEvent
SetCriticalSectionSpinCount
SetEvent
SetWaitableTimer
SignalObjectAndWait
TimerAPCProc
TryEnterCriticalSection
WaitForMultipleObjects
WaitForMultipleObjectsEx
WaitForSingleObject
WaitForSingleObjectEx