//////////////////////////////////////////////////
//
//实验四:使用文件映射对象实现线程间同步
//
//学号:和谐
//
//姓名:和谐
//
//时间:2012年5月21日
//
//////////////////////////////////////////////////
//
//本程序创建一个27字节的文件,填进去26个字母,结尾是NULL
//然后创建两个线程
//一个将大写转化为小写并输出,一个将小写转化为大写并输出
//
//////////////////////////////////////////////////
#include <Windows.h>
#include <stdio.h>
#include <ctype.h>
#define N 26

DWORD WINAPI ThreadProc_1(LPVOID lpParam);
DWORD WINAPI ThreadProc_2(LPVOID lpParam);

int main(int argc, char** argv)
{
    //在当前目录下创建一个"data.dat"文件
    WCHAR path[MAX_PATH];
    DWORD dwRet = GetCurrentDirectory(MAX_PATH, path);
    lstrcat(path, L"\\data.dat");

    //PWCHAR path = L".\\data.dat";
    HANDLE file_create = CreateFile(
        path,
        FILE_ALL_ACCESS,
        FILE_SHARE_READ|FILE_SHARE_WRITE, 
        NULL,
        CREATE_ALWAYS,
        FILE_FLAG_RANDOM_ACCESS,
        NULL);
    if(file_create == NULL)
    {
        printf("创建文件失败!\n");
        exit(0);
    }
    if(GetLastError() == ERROR_ALREADY_EXISTS)
    {
        printf("将已存在的文件覆盖!\n");
    }

    //写入26个小写字母
    char table[N+1];
    for(int i=0; i<N; i++)
    {
        table[i] = 'a'+i;
    }
    table[N] = '\0';
    DWORD bytes_written = 0;
    if(WriteFile(
        file_create,
        table,
        N+1,
        &bytes_written,
        NULL) == 0)
    {
        printf("写入文件失败!\n");
        exit(0);
    }

    //创建文件映射
    HANDLE file_map = CreateFileMapping(file_create,
        NULL,
        PAGE_READWRITE,
        0,
        N+1,
        L"miao");
    if(file_map == NULL)
    {
        printf("创建文件映射失败!\n");
        exit(0);
    }

    //创建互斥对象
    HANDLE ghMutex = CreateMutex(
        NULL,
        false,
        TEXT("xiaoma"));
    if(ghMutex == NULL)
    {
        printf("创建互斥对象失败!\n");
        exit(0);
    }

    //创建子线程
    HANDLE hThread_1,hThread_2;
    hThread_1 = CreateThread(
        NULL,
        0,
        ThreadProc_1,
        file_map,//这里不必进行强制转化
        0,
        NULL);
    hThread_2 = CreateThread(
        NULL,
        0,
        ThreadProc_2,
        file_map,
        0,
        NULL);

    Sleep(1000);
    CloseHandle(file_create);
    CloseHandle(file_map);
    //程序结束,删除文件,返回
    int iret = DeleteFile(path);
    if(iret == 0)
    {
        printf("删除文件失败!\n");
        DWORD err = GetLastError();
        switch(err)
        {
        case ERROR_FILE_NOT_FOUND:
            printf("cannot find the file!\n");
            break;
        case ERROR_ACCESS_DENIED:
            printf("this file is read only!\n");
            break;
        default:
            break;
        }
        getchar();
    }
    return 0;
}

DWORD WINAPI ThreadProc_1(LPVOID lpParam)
{
    for(int k=0; k<100; k++)
    {
        HANDLE ghMutex = OpenMutex(MUTEX_ALL_ACCESS, false, TEXT("xiaoma"));
        if(ghMutex == NULL)
        {
            printf("error!\ncannot open the mutex!\n");
            return -1;
        }
        if(WaitForSingleObject(ghMutex, INFINITE) == WAIT_OBJECT_0)
        {
            //打开文件映射
            HANDLE  file_map = lpParam;
            LPVOID data = MapViewOfFile(
                file_map,
                FILE_MAP_ALL_ACCESS,
                0,
                0,
                N+1);
            if(data == NULL)
            {
                printf("打开文件映射失败!\n");
                return -1;
            }

            //如果文件中字符为小写,
            //则将小写转化为大写
            char* temp = (char*)data;
            if(islower(temp[0]) != FALSE)
            {
                printf("原始字符串:\n%s\n",temp);
                for(int i=0; i<N; i++)
                {
                    temp[i] = toupper(temp[i]);
                }
                printf("转化为大写之后的字符串:\n%s\n\n",temp);
            }
            UnmapViewOfFile(data);
            ReleaseMutex(ghMutex);
        }
    }
    return 0;
}
DWORD WINAPI ThreadProc_2(LPVOID lpParam)
{
    for(int k=0; k<100; k++)
    {
        HANDLE ghMutex = OpenMutex(MUTEX_ALL_ACCESS, false, TEXT("xiaoma"));
        if(ghMutex == NULL)
        {
            printf("error!\ncannot open the mutex!\n");
            return -1;
        }
        if(WaitForSingleObject(ghMutex, INFINITE) == WAIT_OBJECT_0)
        {
            //打开文件映射
            HANDLE  file_map = lpParam;
            LPVOID data = MapViewOfFile(
                file_map,
                FILE_MAP_ALL_ACCESS,
                0,
                0,
                N+1);
            if(data == NULL)
            {
                printf("打开文件映射失败!\n");
                return -1;
            }

            //如果文件中字符为大写,
            //则将大写转化为小写
            char* temp = (char*)data;
            if(isupper(temp[0]) != FALSE)
            {
                printf("原始字符串:\n%s\n",temp);
                for(int i=0; i<N; i++)
                {
                    temp[i] = tolower(temp[i]);
                }
                printf("转化为小写之后的字符串:\n%s\n\n",data);
            }
            UnmapViewOfFile(data);
            ReleaseMutex(ghMutex);
        }
    }
    return 0;
}

 

 

关于这个程序的问题有两点

第一,创建的进程,其返回值返回到哪里了

第二,创建的文件在哪里?为何运行的时候我在当前目录下没找到?

第二个问题已解决。我本来想着直接创建文件的时候,在前面加上".\\"就可以在当前文件下创建了

结果不是的。现在用GetCurrentDirectory函数取得当前目录然后加上文件名实现了

但是又引出了新的问题:

为什么这时候创建的文件所在目录不是程序编译链接生成的exe文件所在的目录呢?