⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdc.c

📁 <Win2k系统编程>源码.次数为国人自编,内容丰富,还是不错的.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++
Module Name:
    pdc.c
Abstract:
    This is the main source file for the Windows/NT PDC API demonstration
    program.  This program demonstrates how to use many of the advanced
    operating system features provided by the Win32 API set on Windows/NT.

    This file and its corresponding header file, pdc.h, can be found
    in the sample programs directory of the PDC CD-ROM.

    This program has a real purpose, although the implementation is
    somewhat contrived in order to demonstrate the various operating
    system features of Windows/NT.

    The features that this program demonstrate are:

        - Creating multiple threads, using critical sections
          and semaphores for synchronization.

        - Thread termination.

        - Virtual memory, commitment vs reservation.

        - Structured exception handling, including finally
          clauses and an exception filter procedure.

        - Enumeration of directory entries.

        - Mapped file I/O

        - Asynchronous file I/O via completion routine.

        - Synchronous file I/O

    PDC is a character mode program for searching the files in a
    directory tree for a match against a pattern.  It uses multiple
    threads to do it's work, with each thread processing a file at a
    time, accumulating it's matches and outputting them to standard
    output contiguously when it is done searching a file.

    The command line syntax is:

        Usage: PDC [-h] [-v] [-y] [-a | -s | -m] [-t n] SearchString [DirectoryPath]

        where:

            -h - prints this message.

            -v - generates verbose output.

            -y - ignores case when doing comparisons.

            -a - specifies that the program should use asynchronous file
                 I/O to read the files being searched.

            -s - specifies that the program should use synchronous file
                 I/O to read the files being searched.

            -m - specifies that the program should use mapped file I/O
                 to read the files being searched.

            -t - specifies the number of threads to use when doing the
                 search.  Default is 4 * the number of processors.

            SearchString - specifies the text to search for.  Enclose in
                           quotes if it contains spaces or punctuation.

            DirectoryPath - specifies the root of the tree to begin the
                            search at.  Defaults to the current directory.


--*/

#include "pdc.h"


int
main(
    int argc,
    char *argv[]
    )

/*++

Routine Description:

    This is the main procedure for the PDC program, and is called by
    the C Runtime startup code when the program starts.

Arguments:

    argc - number of argumments in the argv array.

    argv - pointer to an array of null terminated string pointers.

Return Value:

    Process exit status.  The value returned by this function will
    be used as the exit code parameter passed to ExitProcess.

--*/

{
    SYSTEM_INFO SystemInformation;
    PWORK_QUEUE WorkQueue;

    //
    // Query the number of processors from the system and
    // default the number of worker threads to 4 times that.
    //

    GetSystemInfo( &SystemInformation );
    NumberOfWorkerThreads = SystemInformation.dwNumberOfProcessors * 4;

    //
    // Process the arguments given on the command line.
    //

    if (!ProcessCommandLineArguments( argc, argv )) {
        exit( 1 );
        }

    //
    // Allocate a thread local storage slot for use by our worker
    // thread routine (ProcessRequest).  This call reserves a
    // 32-bit slot in the thread local storage array for every
    // thread in this process.  Remember the slot index in a global
    // variable for use by our worker thread routine.
    //

    TlsIndex = TlsAlloc();
    if (TlsIndex == 0xFFFFFFFF) {
        fprintf( stderr, "PDC: Unable to allocated thread local storage.\n" );
        exit( 1 );
        }


    //
    // Create a work queue, which will create the specified number of threads
    // to process.
    //

    WorkQueue = CreateWorkQueue( NumberOfWorkerThreads, ProcessRequest );
    if (WorkQueue == NULL) {
        fprintf( stderr, "PDC: Unable to create %u worker threads.\n", NumberOfWorkerThreads );
        exit( 1 );
        }

    //
    // If using asynchronous I/O, create an event that will be signalled
    // when there are no more outstanding I/O requests.  The event is
    // a manual reset event, that once signalled via SetEvent, will
    // remain signalled until ResetEvent is called.
    //

    if (ASyncIO) {
        IoCompletedEvent = CreateEvent( NULL,   // Not inherited
                                        TRUE,   // Manual reset
                                        FALSE,  // Initially reset
                                        NULL    // No name
                                      );
        }

    //
    // Now walk the directory tree, which will call our procedure
    // (QueueSearchFile) for each directory and file in the tree.
    //

    EnumerateDirectoryTree( DirectoryPath,
                            QueueSearchFile,
                            WorkQueue
                          );

    //
    // Done walking the tree.  If using asynchronous I/O, wait for all of
    // the outstanding I/O requests to be completed.
    //

    if (ASyncIO) {
        //
        // We use an alertable wait in a loop, as I/O completion
        // will terminate the wait, even through the event we
        // are waiting on is not signalled.
        //

        while (WaitForSingleObjectEx( IoCompletedEvent,
                                      0xFFFFFFFF,
                                      TRUE
                                    ) == WAIT_IO_COMPLETION
              ) {
            ;
            }
        }

    //
    // All done, destroy the work queue.  This will wait for the work queues
    // to empty before terminating the worker threads and destroying the
    // queue.
    //

    DestroyWorkQueue( WorkQueue );

    if (Verbose && MatchedLineCount) {
        fprintf( stderr,
                 "Found %u lines with matches in %u files, out of %u files searched.\n",
                 MatchedLineCount,
                 MatchedFileCount,
                 SearchedFileCount
               );
        }

    return 0;
}



VOID
QueueSearchFile(
    LPSTR Path,
    PWIN32_FIND_DATA FindFileData,
    PVOID EnumerateParameter
    )

/*++

Routine Description:

    This is the directory enumeration function.  It is called by the
    EnumerateDirectoryTree function once for each file and directory
    in the tree.

    This function, if it decides it wants to search the file, will
    open the file and then, depending upon the I/O method selected via
    the command line, will:

        - map the file PAGE_READONLY for mapped file I/O

        - read the file into an allocated buffer for synchronous
          I/O.

        - will allocate the buffer and start a read operation
          to read the entire file into the buffer.  A completion
          routine will be invoked when the read completes, possibly
          in another thread context.

    Finally it will queue a search request to the work queue, with the
    relevant information contained in the request.  For asynchronous
    I/O, the search request is allocated and initialized here but is
    not actually queued to the work queue until the I/O completion
    routine has been called.

Arguments:

    Path - Supplies a pointer to a null terminated string that contains
        the fully qualified path of the file or directory.

    FindFileData - Supplies the directory information associated
        with the file or directory specified by the Path argument.

    EnumerateParameter - Uninterpreted 32-bit value.  Not used.

Return Value:

    None.

--*/

{
    PWORK_QUEUE WorkQueue = (PWORK_QUEUE)EnumerateParameter;
    PSEARCH_REQUEST SearchRequest;
    HANDLE File;
    HANDLE Mapping;
    LPVOID FileData;
    DWORD FileSize;

    //
    // Ignore directories or zero length files, as there
    // is nothing to search in these cases.
    //

    if (FindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ||
        !(FileSize = FindFileData->nFileSizeLow)
       ) {
        return;
        }

    //
    // Open the file using the fully qualified path.  Specify the
    // sequential scan hint to the cache manager and if asynchronous
    // I/O will be used, specified the overlapped flag as well.
    //

    File = CreateFile( Path,
                       GENERIC_READ,
                       FILE_SHARE_READ,
                       NULL,
                       OPEN_EXISTING,
                       FILE_FLAG_SEQUENTIAL_SCAN |
                         (ASyncIO ? FILE_FLAG_OVERLAPPED : 0),
                       NULL
                     );

    //
    // Since NULL might be a valid file object handle, failure
    // is indicated by a special return value.
    //

    if (File == INVALID_HANDLE_VALUE) {
        fprintf( stderr, "%s(0) : error %u: Unable to open file.\n",
                 Path,
                 GetLastError()
               );

        return;
        }

    //
    // File successfully opened for read access.
    //
    if (MappedFileIO) {
        //
        // If mapped file I/O, create a file mapping object, backed by
        // the file we just opened.  Make the default page protection
        // for the mapping be readonly.
        //

        Mapping = CreateFileMapping( File,
                                     NULL,
                                     PAGE_READONLY,
                                     0,
                                     0,
                                     NULL
                                   );

        //
        // Okay to close the file handle now, since the mapping object
        // has a reference to the file that will cause the open file
        // object to remain until the reference is destroyed.  Note that
        // any sharing information is lost at this point, so somebody
        // could come in an open it for write access.
        //

        CloseHandle( File );

        //
        // Here, a null value indicates an error.
        //

        if (Mapping == NULL) {
            fprintf( stderr, "%s(0) : error %u: Unable to create mapping object.\n",
                     Path,
                     GetLastError()
                   );
            return;
            }

        //
        // Finally, map a view of the file, using the mapping object
        // just created, into the address space of this process.
        // The offset and size are zero, which means to map the
        // entire file.
        //

        FileData = MapViewOfFile( Mapping,
                                  FILE_MAP_READ,
                                  0,
                                  0,
                                  0
                                );

        //
        // Okay to close the mapping object handle now, it will remained
        // referenced as long as the view remains mapped.
        //

        CloseHandle( Mapping );

        //
        // A null value indicates the map operation failed.
        //

        if (FileData == NULL) {
            fprintf( stderr, "%s(0) : error %u: Unable to map file.\n",
                     Path,
                     GetLastError()
                   );
            return;
            }

        //
        // All done mapping the file.  Set the File handle to NULL as
        // it has been closed already.  Both the file object and mapping
        // objects created above will be freed when the map view is
        // unmapped.
        //

        File = NULL;
        }
    else {
        //
        // Not using mapped I/O, so allocate a buffer big enough to
        // contain the entire file.
        //

        FileData = VirtualAlloc( NULL,
                                 FileSize,
                                 MEM_COMMIT,
                                 PAGE_READWRITE
                               );
        if (FileData == NULL) {
            fprintf( stderr, "%s(0) : error %u: Unable to allocate memory to contain file.\n",
                     Path,
                     GetLastError()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -