int _tmain (DWORD argc, LPTSTR argv [])
/* Create a separate process to search each file on the
command line. Each process is given a temporary file,
in the current directory, to receive the results. */
{
HANDLE hTempFile;
SECURITY_ATTRIBUTES StdOutSA = /* SA for inheritable handle. */
{sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
TCHAR CommandLine [MAX_PATH + 100];
STARTUPINFO StartUpSearch, StartUp;
PROCESS_INFORMATION ProcessInfo;
DWORD iProc, ExCode;
HANDLE *hProc; /* Pointer to an array of proc handles. */
typedef struct {TCHAR TempFile [MAX_PATH];} PROCFILE;
PROCFILE *ProcFile; /* Pointer to array of temp file names. */
/* Create a separate "grep" process for each file on the
command line. Each process also gets a temporary file
name for the results; the handle is communicated through
the STARTUPINFO structure. argv [1] is the search pattern. */
for (iProc = 0; iProc < argc - 2; iProc++) {
/* Create a command line of the form: grep argv [1] argv [iProc + 2] */
/* Processes are all running. Wait for them to complete, then output
the results - in the order of the command line file names. */
for (iProc = 0; iProc < argc-2; iProc += MAXIMUM_WAIT_OBJECTS) WaitForMultipleObjects (min(MAXIMUM_WAIT_OBJECTS, argc - 2 - iProc),
&hProc[iProc], TRUE, INFINITE);
/* Result files sent to std output using "cat".
Delete each temporary file upon completion. */
for (iProc = 0; iProc < argc - 2; iProc++) {
if (GetExitCodeProcess (hProc [iProc], &ExCode) && ExCode == 0) {
/* Pattern was detected - List results. */
/* List the file name if there is more than one file to search */
if (argc > 3) _tprintf (_T("%s:\n"), argv[iProc+2]);
fflush (stdout); /* required by multiple processes using stdout */
_stprintf (CommandLine, _T ("%s%s"),
_T ("cat "), ProcFile [iProc].TempFile);
if (!CreateProcess (NULL, CommandLine, NULL, NULL,
TRUE, 0, NULL, NULL, &StartUp, &ProcessInfo))
ReportError (_T ("Failure executing cat."), 0, TRUE);
else { WaitForSingleObject (ProcessInfo.hProcess, INFINITE); CloseHandle (ProcessInfo.hProcess); CloseHandle (ProcessInfo.hThread);
}
}
/* Wait for the producer and consumer to complete */
Status = WaitForSingleObject (consume_h, INFINITE);
if (Status != WAIT_OBJECT_0)
ReportError (_T("Failed waiting for consumer thread"), 3, TRUE);
Status = WaitForSingleObject (produce_h, INFINITE);
if (Status != WAIT_OBJECT_0)
ReportError (__T("Failed waiting for producer thread"), 4, TRUE);
DeleteCriticalSection (&mblock.mguard);
return 0;
}
뮤텍스
CreateMutex()
OpenMutex()
CloseHandle()
WaitForSingleObject()
WaitForMultipleObjects()
ReleaseMutex()
세마포어
다중 대기시 문제가 있다.
CreateSemaphore()
OpenSemaphorer()
CloseHandle()
WaitForSingleObject()
WaitForMultipleObjects()
ReleaseSemaphore()
//
// Allocated for each client connection
//
typedef struct _CONNECTION_OBJ
{
SOCKET s; // Client socket
HANDLE hRecvSema; // Semaphore incremented for each receive
struct _BUFFER_OBJ *PendingSendHead, // List of pending buffers to send
*PendingSendTail; // End of the list
CRITICAL_SECTION SendRecvQueueCritSec; // Protect access to this structure
} CONNECTION_OBJ;
//
// Function: ReceiveThead
//
// Description:
// One of these threads is started for each client connection.
// This thread sits in a loop, receiving data. For each receive, the
// buffer is queued for sending by the SenderThread for this connection.
//
DWORD WINAPI ReceiveThread(LPVOID lpParam)
{
CONNECTION_OBJ *ConnObj=NULL;
BUFFER_OBJ *BuffObj=NULL;
int rc;
// Retrieve the connection object for this connection
ConnObj = (CONNECTION_OBJ *)lpParam;
if (gProtocol == IPPROTO_UDP)
{
// For UDP all we do is receive packets on the port
while (1)
{
// Allocate the buffer for datagram send/recv
BuffObj = GetBufferObj(gBufferSize);
BuffObj->buflen = rc;
/*
if (rc > 0)
{
}
*/
// Queue the receive buffer for sending and signal the send thread
EnqueueBufferObj(ConnObj, BuffObj);
ReleaseSemaphore(ConnObj->hRecvSema, 1, NULL);
if (rc == 0)
{
break;
}
}
}
else if (gProtocol == IPPROTO_TCP)
{
// loop until the connection is closed or is aborted/terminated
while (1)
{
// Allocate the buffer for stream send/recv
BuffObj = GetBufferObj(gBufferSize);
//
// Function: SendThread
//
// Description:
// This is the send thread started for each client connection.
// This thread waits for the semaphore to be signaled indicating that
// the receive thread has queued a buffer for sending.
//
DWORD WINAPI SendThread(LPVOID lpParam)
{
CONNECTION_OBJ *ConnObj=NULL;
BUFFER_OBJ *BuffObj=NULL;
int rc,
nleft,
idx;
// Retrieve the connection object
ConnObj = (CONNECTION_OBJ *)lpParam;
while (1)
{
// Wait for the receive thread to signal us
rc = WaitForSingleObject(ConnObj->hRecvSema, INFINITE);
if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT)
{
fprintf(stderr, "WaitForSingleObject failed: %d\n", GetLastError());
ExitProcess(-1);
}
// Retrieve the first buffer from this connection's queue
BuffObj = DequeueBufferObj(ConnObj);
//
// If the this receive by the receive thread indicated zero bytes then
// the connection has been gracefully closed. Otherwise, if an error
// was indicated then the connection was aborted.
//
if ((gProtocol == IPPROTO_TCP ) && ((BuffObj->buflen == 0) || (BuffObj->buflen == SOCKET_ERROR)))
{
FreeBufferObj(BuffObj);
BuffObj = NULL;
break;
}
if (gProtocol == IPPROTO_UDP)
{
// For UDP we send the packet back to the source address
rc = sendto(
ConnObj->s,
BuffObj->buf,
BuffObj->buflen,
0,
(SOCKADDR *)&BuffObj->addr,
BuffObj->addrlen
);
if (BuffObj->buflen == 0)
{
FreeBufferObj(BuffObj);
BuffObj = NULL;
break;
}
}
else if (gProtocol == IPPROTO_TCP)
{
// Otherwise send the buffer on the connection socket
nleft = BuffObj->buflen;
idx = 0;