파일에는 텍스트 파일과 바이너리 파일의 두종류가 있다.
텍스트 파일은 문자 정보로 되어있는 파일이고 윈도우즈에 있는 메모장같은
텍스트 에디터로 편집할 수 있는 파일이다.
에디터로 열어 보면 어떤 데이터가 들어있는지 볼 수 있다.
이에 반해 바이너리 파일은 바이너리, 2진수의 데이터가 나열되어있는 파일로
16진수로 변환하여 덤프 표시를 해주는 프로그램을 사용해서 볼수 있다.
그렇게 본다고 해도 사람이 이해할 수 있는 데이터인 경우도 있지만
주로 이해할 수 없는 데이터들일 것이다.

예를 들면 C언어의 소스 파일은 텍스트 파일이지만 소스 파일을 컴파일/링크하여
생기는 오브젝트 파일(*.obj파일)이나 실행 파일은 바이너리 파일이다.
이런 파일을 텍스트 에디터로 읽어봐도 무슨 의미인지 알 수 없다.
그러나 컴퓨터에게 있어서는 의미가 있는 2진수의 나열이기 때문에 소스 파일에
짜여진 처리를 실행 형식의 파일에서 읽어서 실행할 수 있다.
그 외에도 그림 데이터, 음악 데이터나 워드로 만든 문서 파일도 서식 정보를 가지고 있는
바이너리 파일이다.

텍스트 파일과 바이너리 파일외에도 데이터의 기록하는 방식에 따라서
시퀀셜 파일이나 랜덤 파일로 나누어진다.
C에서는 각각의 기록 방식이 틀리지는 않지만 파일을 억세스하는데 있어서
시퀀셜 억세스와 랜덤 억세스가 있다 시퀀셜 억세스는 파일의 처음부터
순차적으로 읽는 방법이다. 이에반해 램덤 억세스는 파일의 임의의 위치부터
읽거나 쓸수있는 방법으로 하드디스크 억세스와 비슷하다.

================================================================================

파일을 열고 닫기(fopen, fclose)

파일의 데이터를 읽고 쓰기 위해서는 파일을 열어야된다.
예제 1은 파일을 읽어서 파일의 내용을 표시하고 파일을 닫는다.

#include  <stdio.h>

int main()
{
    FILE *fp;
    int nChar;

    if((fp = fopen("test.txt", "r")) == NULL)
        return(1);

 while((nChar = fgetc(fp)) != EOF){
        putchar(nChar);
 }

 fclose(fp);
 return(0);
}

예제 1 텍스트 파일을 열어 파일의 내용을 표시하고 닫는 예제



함수명
형식
처리내용
fopen FILE *fopen(
    const char *filename
    const char *mode);
filename의 파일을 열어서 FILE구조체에 포인터를
반환한다. mode는 테이블2 참조
fclose int fclose(FILE *fp) fopen에서 연 파일의 포인터(fp)로 파일을 닫는다.
테이블 1 파일 열고 닫는 함수


모드
의미
r 읽기 전용으로 파일 열기.
기존 파일이 없으면 에러를 반환
w 쓰기 전용으로 파일 열기.
기존 파일이 있으면 덮어쓰고 기존 파일이 없으면 새로 작성
a 덧붙여 쓰기로 파일 열기
기존 파일이 있으면 파일 끝에서부터 데이터 추가
기존 파일이 없으면 새로 작성
테이블 2 파일 열기 모드

+가 붙으면 r+, w+, a+가 붙으면 읽기, 쓰기 모두가 가능하게 된다.

fopen 함수는 파일 열기에 성공하며 파일의 포인터를 반환한다. 파일 포인터는 FILE구조체의 포인터이다. FILE구조체에의 포인터 fp에는 그 파일에 억세스하기 위해 필요한 정보에의 참조가 설정되어있다. 파일이 없거나해서 파일 열기에 실패하면 fopen 함수는 NULL을 반환한다.

fgetc함수는 파일로부터 한 문자씩 읽어 들인다. EOF를 반환할 때까지 한 문자씩 읽는 것을 반복한다. putchar 함수로 표준 출력으로 표시한다. 또 파일은 사용이 끝나면 파일을 닫아야된다. 파일 포인터 fp를 닫는다.


함수명
형식
처리내용
fgetc int fgetc(FILE *fp); 파일에서 한 문자씩 읽고 일어들인 문자를 반복한다.
파일의 끝이나 에러일 경우에 EOF를 반환한다.
fputc int fputc(int c, FILE *fp); 파일에 한 문자씩 쓰고, 쓴 문자를 반환한다. 에러일 경우에 EOF를 반환한다.
테이블 3 문자 입출력에 관한 함수


  예제2에서는 fpi, fpo로 입력과 출력용 파일 포인터를 선언하고 있다 또 파일명을 scanf 함수로 받아서 입력된 파일명의 파일을 열 수없는 경우 putchar에서 "\a"로 비프음을 울리는 에러 처리로 보내어져 메세지를 보여주고 exit함수로 프로그램을 종료한다. 실행되면 한 문자씩 읽어와서 한 문자씩 써서 파일의 내용을 다른 파일에 카피한다.


#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fpi, *fpo;
    char fname[2][64];
    int nChar;

    printf("입력 파일명 :");
    scanf("%s", fname[0]);
    printf("출력 파일명 :");
    scanf("%s", fname[1]);

    if((fpi = fopen(fname[0], "r")) == NULL){
        putchar('\a');
        printf("\n %s 파일을 열지 못함\n", fname[0]);
        exit(1);
    }
    if((fpo = fopen(fname[1], "w")) == NULL){
        putchar('\a');
        printf("\n %s 파일을 열지 못함\n", fname[1]);
        exit(1);
    }
    while((nChar = fgetc(fpi)) != EOF){
        fputc(nChar, fpo);
    }

    fclose(fpi);
    fclose(fpo);
    return(0);
}

예제 2 텍스트 파일을 내용을 카피하는 예제


예제3에서 파일을 열어서 fgets로 라인으로 읽고 puts로 라인을 출력한다.
파일이름은 커맨드 라인의 첫번째 인수로 메인 함수에서 넘겨준다.
(디버그할 때 명령 인수를 넘기는 방법은 프로젝트 메뉴의 속성을 선택하고
트리뷰의 구성 속성의 디버깅을 선택한 후, 명령 인수에 읽어올 파일명을 입력한다.)

#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>

int main(int argc, char *argv[])
{
    FILE *fp;
    char szLine[256];

    if(argc < 2)
        exit(1);

    if((fp = fopen(argv[1], "r")) == NULL)
        exit(1);

    while(fgets(szLine, 256, fp) != NULL){
        szLine[strlen(szLine) - 1] = '\0';
        puts(szLine);
    }
    fclose(fp);
    return(0);
}

예제 3 파일을 열어 라인으로 읽고 라인으로 출력하는 예제

예제 3에서 밑의 행이 들어간 이유는 행을 읽어오고 puts를 이용하여 출력할 때 "\0"이 "\n"으로 바뀌어 개행이 됨으로 두줄이 되기 때문에 밑의 방법을 이용하여 2줄씩 띄어지는 것을 방지한다.
   szLine[strlen(szLine) - 1] = '\0';
fgets로 읽어온 한 행 데이터
h a h a \n \0
puts로 출력                                ↓
h a h a \n \n

puts함수로 행을 출력하면 \0이
\n으로 바뀌어 2줄씩 띄어짐
fgets로 읽어온 한 행 데이터
h a h a \n \0
szLine[strlen(szLine) - 1] = '\0';
h a h a \0 \0
puts로 출력                      ↓
h a h a \n

함수명
형식
처리내용
fgets char *fgets(char * str, int n, FILE *fp); 파일에서 한 행씩 읽어 들인다. n-1개의 문자 문자의 개행 문자를 읽는 시점에서 종료한다.
파일의 끝이나 에러일 경우에 NULL을 반환한다.
fputs int fputs(const char *str, FILE *fp); 파일에서 1행씩 출력하고 정상일 때 양수값을 반환한다. 에러일 경우에 EOF를 반환한다.
테이블 4 행단위 입출력에 관한 함수


표준 입력, 표준 출력, 표준 에러 출력 이것들도 파일이다.

파일이라는 것은 열어서 쓰거나 반드시 닫아야 된다. 파일 이외에도 이렇게 반드시 열고 닫아야되는 것이 세가지 있다. 표준 입력, 표준 출력, 표준 에러 출력이라 불리는 파일들이다.

밑의 그림과 같이 표준 입력(stdin)은 키보드로 표준 출력(stdout)과 표준 에러 출력(stderr)은 디스플레이에 설정된다. 키보드나 디스플레이가 파일이라는 것은 왠지 느낌이 안 와닿을 수 있다. 하지만 워낙 UNIX계열의 OS개발을 위해 만들어진 C언어에서는 키보드나 디스플레이 등의 주변 기기도 파일 취급을 한다.

사용자 삽입 이미지

  fputs(szLine, stdout);

위와같이 하면 출력할 곳을 stdout(표준 출력)으로 변경하여 실행하면 넘겨진 문자열을 화면에 표시한다. 결국 표준 출력도 파일과 같이 취급할 수 있다. 표준 입력, 표준 출력, 표준 에러 출력은 프로그램의 시작할 때 자동적으로 열리고 프로그램이 종료될 때 자동으로 파일이 자동으로 닫친다고 생각하면 된다.

C언어에서는 표준 입력뿐 아니라 모든 파일을 읽고 쓸 경우에는 버퍼를 사용하여 스트림 입출력을 행한다. 스트림 입출력에서는 함수가 직접 파일을 억세스하지않고 사이에 버퍼를 통하여 입출력을 한다. 프로그램은 버퍼로부터 읽고 버퍼에 쓴다. 버퍼가 비면 OS는 자동적으로 파일로 부터 읽어온다. 버퍼가 가득차면 버퍼로 부터 파일에 씌여지게 된다. 이 원리에 의해 C언어에서는 효율적으로 파일에 억세스할 수 있다.


서식을 붙이는 함수

표준 입출력에서 서식을 붙여서 입출력할 수 있다.

함수명
형식
처리내용
fscanf int fscanf(FILE *fp, const char *format, ...); 서식 format에 따라서 파일로 부터 인수에 데이터를 저장한다. 파일 엔드나 에러의 경우 EOF을 반환한다.
fprintf int fprintf(FILE *fp, const char *format, ...); 서식 format에 따라서 파일에 데이터를 출력하고 출력된 바이트 수를 반환한다. 에러의 경우는 EOF를 반환한다.
테이블 5 서식 입출력에 관한 함수

fscanf와 fprintf 함수를 사용하는 예제5는 테스트 파일을 행 단위로 읽어 행번호를 붙여서 파일을 출력하는 프로그램이다. fprintf 함수로 출력 파일에 서식을 붙여서 저장한다. 파일명의 입력에도 파일이 아니라 stdin(표준 입력 : 키보드)로 부터 읽어오게 되어있다. 오픈 에러가 발생했을 때는 fprintf 함수의 인수에 stderr(표준 에러 출력)을 지정하여 도스창에 에러를 표시한다.


#include  <stdio.h>
#include  <stdlib.h>

int main()
{
    FILE *fpi;
    FILE *fpo;
    char szFilei[64];
    char szFileo[64];
    char szBuff[256];
    unsigned int nLines = 0;

    printf("입력 파일명 입력 : ");
    fscanf(stdin, "%s", szFilei);

    if((fpi = fopen(szFilei, "r")) == NULL){
        putchar('\a');
        fprintf(stderr, "\n %s 를 열 수 없습니다.\n", szFilei);
        exit(1);
    }
    printf("출력 파일명 입력 : ");
    fscanf(stdin, "%s", szFileo);

    if((fpo = fopen(szFileo, "w")) == NULL){
        putchar('\a');
        fprintf(stderr, "\n %s 를 열 수 없습니다.\n", szFileo);
        exit(1);
    }

    while(fgets(szBuff, 256, fpi) != NULL){
        fprintf(fpo, "%5d: %s", ++nLines, szBuff);
    }
    fclose(fpi);
    fclose(fpo);
    return(0);
}

예제 4 텍스트 파일을 열어 행 번호를 붙여 다른 파일로 출력하는 예제



Posted by 띠리
소스1

int n = 0;

HANDLE hFile = CreateFile(sPath,
    GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);

if(hFile == INVALID_HANDLE_VALUE)
// 에러
else
{
    char buffer[65536];
    DWORD dwRead;
    int n = 0;
    while(1)
    {
        if(!ReadFile(hFile, buffer, sizeof buffer, &dwRead, NULL) || !dwRead)
            break;
        n += std::count(buffer, buffer + dwRead, '\n');
    }
    CloseHandle(hFile);
}



소스2

static int count_ln_by_buffer (const char *filename)
{
    HANDLE hFile;
    char *start, *p;
    DWORD len, line_num = 0;
    DWORD dwRead;

    hFile = CreateFile (
        filename,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (!hFile)
        return -1;

    len = GetFileSize (hFile, NULL);

    start = p = malloc (len);
    ReadFile (hFile, start, len, &dwRead, NULL);

    for (; (DWORD) (p - start) < len; p++)
    {
        if (*p == '\n')
        line_num++;
    }

    CloseHandle (hFile);

    return line_num;
}

static int count_ln_by_file_mapping (const char *filename)
{
    HANDLE hFile, hMap;
    const char *start, *p;
    DWORD len, line_num = 0;

    hFile = CreateFile (
        filename,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    if (!hFile)
        return -1;

    hMap = CreateFileMapping (
        hFile,                     /* Current file handle */
        NULL,                    /* Default security */
        PAGE_READONLY,  /* Read/write permission */
        0,                          /* Max. object size. */
        0,                          /* Size of hFile */
        NULL);                   /* Name of mapping object */

    if (!hMap)
        return -1;

    start = p = MapViewOfFile (
        hMap,                    /* Handle to mapping object */
        FILE_MAP_READ,    /* Read/write permission */
        0,                          /* Max. object size. */
        0,                          /* Size of hFile */
        0);                        /* Map entire file */

    if (!p)
        return -1;

    len = GetFileSize (hFile, NULL);

    for (; (DWORD) (p - start) < len; p++)
    {
        if (*p == '\n')
            line_num++;
    }

    CloseHandle (hMap);
    CloseHandle (hFile);

    return line_num;
}

int main (int argc, char *argv[])
{
    if (argc <= 1)
        return -1;

    return count_ln_by_buffer (argv[1]);
}


Posted by 띠리

VB

IIf(Expression, TruePart, FalsePart)

C

(Expression ? TruePart: FalsePart )
Posted by 띠리
태그 IIf
설명은 따로 필요없을 것같다.
그냥 밑에 소스를 보면....

void main()

{

    int    nDec = 0;

    char szHex[16];


    // 16진수를 10진수로


    sprintf(szHex, "FF");


    nDec = (int)strtol(szHex, NULL, 16);


    printf(" %s -> %d \n", szHex, nDec);


    nDec = nDec - 0xF;


    // 10진수를 16진수로


    sprintf(szHex, "%X", nDec);


    printf("%d -> %s \n", nDec, szHex);


}



실행한 결과

 FF -> 255
240 -> F0


strtol 함수를 알면 16진수를 10진수로 바꾸는 것을 한줄에 끝낼 수 있는데
저 함수를 모르면...

sprintf의 포멧에서 %X를 쓰느냐 %x를 쓰느냐에
따라서 16진수의 영문자(A~F)가 대문자로 표시되느냐
소문자로 표시되느냐가 결정되어진다.
Posted by 띠리
CreateSemaphoreWaitForSingleObject을 이용하여
어떤 어플리케이션을 한번에 3개까지만 실행 하게하기




#include <stdio.h>

#include <windows.h>


#define SEMAPHORE_NAME "Semaphore Sample"


// 어플리케이션을 한번에 3개까지만 실행 하게

int main()

{

    HANDLE hSemaphore;

    DWORD dwResult;



    // 세마포어 만들기

    hSemaphore = CreateSemaphore(NULL, 3, 3, (LPCSTR)SEMAPHORE_NAME);


    // 지정한 오브젝트가 시그널 상태가 되

    dwResult = WaitForSingleObject(hSemaphore,    // 세마포어 오브젝트 핸들

                                   0);            // 타임아웃시간


    // 만들어진 세마포어 확인

    if(dwResult != WAIT_OBJECT_0) {

        printf("벌써 3개 실행됬어   %d\n", dwResult);

        Sleep(1000);

    } else {

        // 처리

        printf("처리시작   %d\n", dwResult);

        Sleep(10000);

        printf("처리종료   %d\n", dwResult);


        // 개방

        ReleaseSemaphore(hSemaphore, 1, NULL);

    }


    CloseHandle(hSemaphore);

    return(0);

}





vs2005용 예제 파일



프로그램을 빌드해서 실행하면 처리시작이 표시되는 프로그램은 항상 세개이다.
Posted by 띠리
플렛폼 SDK

CreateSemaphore

유명한 혹은 무명한 세마포어 오브젝트를 만들거나 Open한다.

HANDLE CreateSemaphore(
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // 시큐리티 기술자
  LONG lInitialCount,                          // 초기 카운트
  LONG lMaximumCount,                          // 최대 카운트
  LPCTSTR lpName                               // 오브젝트 이름
);
파라미터
lpSemaphoreAttributes

자식 프로세스가 얻은 핸들을 계승할 것인가를 결정한다.1개의 SECURITY_ATTRIBUTES 구조체에의 포인터를 지정한다.
NULL로 지정하면 자식 프로세스는 그 핸들을 계승할 수 없다.

Windows NT/2000:SECURITY_ATTRIBUTES 구조체의 lpSecurityDescriptor 멤버로 새로운 세마포어의 시큐리티 기술자를 설정한다. NULL로 지정하면 디폴트 값이 세마포에 할당된다.

lInitialCount

세마포어 오브젝트의 초기 카운트를 지정한다.
0 이상 lMaximumCount 이하의 값을 지정한다. 세마포어는 카운트가 0보다 큰 경우는 시그널 상태가 되고 카운트가 0일 경우는 비시그널 상태가 된다. 대기 함수(WaitForSingleObject 함수 등)을 사용해서 그 세마포어를 기다리고 있던 스레드를 풀어 주면 카운트가 하나 줄어든다.
ReleaseSemaphore를 사용하면 임의의 수만큼 값을 늘일 수 도 있다.
 
lMaximumCount

세마포어 오브젝트의 최대 값을 지정한다.
0보다 큰 값을 지정해야만 된다.
lpName
 
세마포어 오브젝트의 이름으로 NULL로 끝나는 문자열에 포인터를 지정한다. 이름의 최대 길이는 MAX_PATH의 길이이다. 이름을 비교할 때는 대문자와 소문자를 구별한다.

lpName 파라미터로 지정한 이름이 기존의 세마포어 오브젝트의 이름과 같을 경우,  이 함수를 실행하기위해서는 기존의 오브젝트에 대해서 SEMAPHORE_ALL_ACCESS 엑세스권이 필요한다. 이 경우, lInitialCount 파라미터와 lMaximumCount 파라미터는 오브젝트를 작성한 프로세스에 의해서 이미 설정되어 있기 때문에 무시한다. 또 lpSemaphoreAttributes 파라미터가 NULL이 아닐 경우, 자식 프로세스 핸들을 계승할 것인지를 지정하는 것은 유효하지만 시큐리티 기술자의 멤버는 무시된다.

lpName 파라미터로 NULL 을 지정하면 무명한 세마포어 오브젝트가 만들어진다.

lpName 파라미터로 지정한 이름이 기존의 이벤트, 뮤텍스, 대기 가능한 타이머, 잡, 파일 매핑 오브젝트중에 어떤 것과 같으면 이 함수는 실패하고 GetLastError함수는 ERROR_INVALID_HANDLE을 반환한다. 이것들의 오브젝트는 이름을 저장하는 공간을 공유하고 있기 때문이다.

Terminal Services:
글로벌로 이름을 저장하는 공간 또는 세션 이름을 저장하는 공간으로 오브젝트를 명시적으로 만들기 위해서는「Global\」혹은「Local\」의 prefix를 붙일 수 있다. 이름의 나머지 부분은 원기호(\)를 뺀 임의의 문자를 기술할 수 있다. 상세한 내용은 MSDN 라이브러리 「Kernel Object Name Spaces」를 참조

Windows 2000:Terminal Services가 동작하지 않는 Windows 2000 시스템에서는
「Global\」와「Local\」의 각 prefix는 무시된다.
이름의 나머지 부분은 원기호(\)를 뺀 임의의 문자를 기술할 수 있다.

Windows NT 4.0 이전과 Windows 95/98:이름의 원기호(\)를 뺀 임의의 문자를 기술할 수 있다.

반환값

함수가 성공하면 세마포오 오브젝트의 핸들을 돌려준다.
지정한 세마포어 오브젝트가 이미 존재하고 있는 경우도 이 오브젝트의 핸들을 돌려준다.
이 때 GetLastError함수는 ERROR_ALREADY_EXISTS를 돌려준다.

함수가 실패하면 NULL이 돌아오고 확장 에러 정보를 얻으려면 GetLastError함수를 사용한다.

해설

CreateSemaphore 함수가 돌려주는 핸들에는 새로운 세마포어 오브젝트에의 SEMAPHORE_ALL_ACCESS권이 할당되어져 세마포어 오브젝트의 핸들을 요구하는 임의의 함수로 사용할 수 있다.

호출하는 쪽 프로세스의 임의의 스레드는「wait functions」(대기함수)를 호출할 때에 세마포어 오브젝트의 핸들을 지정할 수 있다. 단일 오브젝트의 대기함수는 지정된 오브젝트가 시그널 상태가 되면 대기 상태에서 빠져나온다. 복수 오브젝트의 대기함수에 대해서는 지정된 오브젝트의 하나(혹은 모든것)이 시그널 상태가 되었을 때에 대기 상태에서 빠져나오도록 지시할 수 있다. 대기함수가 제어권을 돌려주면(대기 상태에서 빠져나오면) 대기중인 스레드가 풀려서 실행기 계속되어진다.

세마포어 오브젝트는 카운트가 0보다 큰 경우는 시그널 상태이고 카운트가 0의 경우는 비시그널 상태가 된다. 대기함수를 사용하여 세마포어를 기다리고 있던 스레드를 풀어주면 카운트가 하나 줄어든다. ReleaseSemaphore 함수를 사용하면 임의의 수만큼 늘일 수 있다. 카운트가 마이너스가 되거나 lMaximumCount 파라미터로 지정한 값보다 커지는 경우는 없다.

복수의 프로세스는 같은 세마포어 오브젝트의 핸들을 할당하여 프로세스간 동기의 목적으로 그 오브젝트를 사용할 수 있다. 다음과 같은 오브젝트 공유 메커니즘을 이용할 수 있다.

CreateSemaphore 함수의 lpSemaphoreAttributes 파라미터로 계승을 유효하게 해두면 CreateProcess함수가 만든 자식 프로세스는 세마포어 오브젝트 핸들을 계승할 수 있다.

•프로세스는 특정 이벤트 오브젝트의 핸들을 지정한 DuplicateHandle 함수를 호출함으로 핸들을 복사할 수 있다. 다른 프로세스는 그 핸들을 사용할 수 있다.

•프로세스는 OpenSemaphore 또는 CreateSemaphore 함수를 호출할 때 이벤트 오브젝트의 이름을 지정할 수 있다.

핸들을 닫을 때는 CloseHandle 함수를 사용한다. 프로세스가 종료될 때에 시스쳄은 그 프로세스가 가지고 있는 핸들을 자동적으로 닫는다. 세마포어 오브젝트에 대해서 하나나 또는 복수의 핸들이 열려있는 경우, 마지막 핸들이 닫힌 시점에서 그 세마포어 오브젝트가 파기되어진다.

대응정보

Windows NT/2000:Windows NT 3.1 이후
Windows 95/98:Windows 95 이후
해더:Winbase.h 안에 선언、Windows.h 을 include
임포트 라이브러리:Kernel32.lib 을 사용
Unicode:Windows NT/2000 は Unicode 판과 ANSI 판을 실장


http://msdn2.microsoft.com/en-us/library/ms682438.aspx

Posted by 띠리

플랫폼 SDK

WaitForSingleObject

지정한 오브젝트가 시그널 상태가 되거나 타임아웃이 되면 제어를 돌려준다.
(지정한 오브젝트가 비시그널 상태이면 시그널 상태가 될때 까지 설정한 타임아웃 시간 만큼WaitForSingleObject에서 대기한다.
당연한 이야기지만 시그널 상태면 바로 다음으로 넘어간다.
)


대기 상태라는 것을 알려주려면 WaitForMultipleObjectsEx 함수를 사용한다.
복수의 오브젝트를 대기하기 위해서는 WaitForMultipleObjects 함수를 사용한다.

DWORD WaitForSingleObject(
  HANDLE hHandle,        // 오브젝트 핸들
  DWORD dwMilliseconds   // 타임아웃 시간
);
파라미터
hHandle
오브젝트의 핸들을 지정한다.
핸들을 지정할 수 있는 함수의 해설을 참조

핸들이 대기 상태로 있을때에는 그 핸들을 없앴을 경우 그 함수의 동작은 정의되지않는다.
(If this handle is closed while the wait is still pending, the function's behavior is undefined. : 동작을 안한다는 이야기인가? -.-)

Windows NT/2000:이 핸들에 SYNCHRONIZE 억세스 권을 할당해야만 된다. 상세한 내용은  MSDN 라이브러리의 「Standard Access Rights」를 참조

dwMilliseconds
타임아웃 시간을 밀리초(ms)단위로 지정한다.
타임아웃 시간을 경과하면 오브젝트가 비시그널 상태에 있더라도 제어권을 돌려준다.(WaitForSingleObject함수에서 더 이상 대기하지않는다.)
0으로 지정하면 이 함수는 지정된 오브젝트의 상태를 확인하고 바로 다음 행을 실행한다.
INFINITE를 지정하면 오브젝트가 시그널 상태가 될때까지 기다린다.
 

반환값

함수가 정상적으로 실행되면 함수 제어권을 돌려준 이유를 알려준다.
값은 아래와 같다.

의미
WAIT_ABANDONED 지정된 오브젝트는 파기 되어진 뮤텍스  오브젝트 였다.
이 뮤텍스 오브젝트를 소유한 스레드가 뮤텍스 오브젝트의 소유권을 풀어주지 않고 종료했다.
그래서 그 뮤텍스 오브젝트의 소유권이 호출한 쪽 스레드로 옮겨져 그 뮤텍스는 비시그널 상태로 설정되었다.
WAIT_OBJECT_0 지정한 오브젝트가 시그널 상태로 되었다.
WAIT_TIMEOUT 지정한 오브젝트가 타임아웃 시간이 경과할 때까지 시그널 생태가 되지 않았다.

함수가 실패하면 WAIT_FAILED이 돌아온다. 확장 에러 정보를 얻기 위해서는 GetLastError 함수를 사용한다.

해설

WaitForSingleObject 함수는 지정한 오브젝트의 현재의 상태를 체크한다.
그 오브젝트가 비시그널 상태일 때는 호출한 스레드는 대기 상태가 된다.
오브젝트가 시그널 상태가 되거나 타임아웃 시간이 경과하는 것을 기다린다.

이 함수는 특정 타임의 동기 오브젝트의 상태를 바꿈으로
지정된 오브젝트가 시그널 상태가 되고 대기 상태에서 빠져나오게 된다.
그리고 세마포어 오브젝트의 카운트를 하나씩 줄인다.

이 함수는 다음의 오브젝트들을 기다릴 수 있다.

•변경 통지(Change notification)
•콘솔 입력(Console input)
•이벤트(Event)
•Memory resource notification
•뮤텍스(Mutex)
•프로세스(Process)
•세마포어(Semaphore)
•스레드(Thread)
•대기 가능한 타이머(Waitable timer)

상세한 내용은 MSDN 라이브러리의「Synchronization Objects」을 참조

이 대기 함수는 윈도우를 직접적 또는 간접적으로 작성하는 코드를 조합해서 사용하는 경우는 주의가 필요한다.
하나의 스레드가 윈도우를 작성하는 경우, 그 스레드는 그 윈도우에 관계하는 메세지를 처리해야된다. 또 메세지 브로드케스트는 시스템 안의 모든 윈도우에 메세지를 보낸다. 타임아웃 시간으로서 INIFINITEㄹ르 지정해서 대기 함수를 호출할 때, 이와 같은 현상이 발생하면 시스템은 데드록(daedlock) 상태에 빠지게 되는 경우도 있다. 윈도우가 간접적으로 작성한 두개의 예로서 DDE와 COM의 CoInitialize가 있다. 그렇기 때문에 윈도우를 작성한 스레드에서는 WaitForSingleObject 함수 말고 MsgWaitForMultipleObjects 함수 나 MsgWaitForMultipleObjectsEx  함수를 사용한다.

대응정보

Windows NT/2000:Windows NT 3.1 이후
Windows 95/98:Windows 95 이후
헤더:Winbase.h 안에서 선언、Windows.h 을 include
임포트 라이브러리:Kernel32.lib를 사용


원문 참고
http://msdn2.microsoft.com/en-us/library/ms687032.aspx

위 譯은 내맘대로 한 것임으로 잘못 譯한 것에 대한 책임 못짐 -.-;;

Posted by 띠리
Visual C++ 2005 Express Edition에서 Win32어플리케이션을
만들기위해서는 몇가지 설정을 해주어야된다.

1) 먼저 Visual C++ 2005 Express Edition 다운로드해서 셋업한다.

2) Microsoft Platform SDK를 다운로드해서 셋업한다.

3) 패스를 설정한다.
  Visual C++ 2005 Express Edition을 시작해서 툴 > 옵션 > 프로젝트 및 솔루션 > VC++ 디렉토리에
  Microsoft Platform SDK의 Bin, Includem lib의 패스를 추가한다.

4) 라이브러리 추가
  C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults
     \corewin_express.vsprops의 AdditionalDependencies의 kernel32.dll의 뒤에
  반각 스페이스를 넣어서 user32.lib gdi32.lib winspool.lib comdlg32.dll advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib 를 추가한다.

5) Win32 템플레이트의 유효화
  C:\Program Files\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic
     \Application\html\1041\AppSettings.htm

    //WIN_APP.disabled=true;
    //WIN_APP_LABEL.disabled=true;
    //DLL_APP.disabled=true;
    //DLL_APP_LABEL.disabled=tu\rue;

  위의 네줄을 코멘트처리한다.

6) 개발환경을 재기동하면 Visual C++ 2005 Express Edition에서 Win32 어플리케이션을
  만들 수 있게된다.

Posted by 띠리
OS에서 제공하는 타이머 함수

  함수                                    측정 단위                                Resolution
---------------------------------------------------------------------------
 Now, Time, Timer                    sec                                       1 sec  
 GetTickCount                         msec                                     거의 10 msec
 TimeGetTime                          msec                                     거의 10 msec
 QueryPerformanceCounter      QueryPerformanceFrequency     같음


음 거의 10msec이라는 것이...
Posted by 띠리

WIN32 SDK에서 시리얼 통신을 하려면...

WinAPI에서는 시리얼 포트도 파일처럼
CreateFile로 파일을 열고
WriteFile로 데이터를 쓰거나
ReadFile로 데이터를 읽거나
CloseHandle로 파일을 닫는다.
일반적으로 파일을 다루는 것과 비슷하지만 시리얼 통신에서는
여기에다가 통신을 하기위한 설정이 필요한다.
SetCommState가 이런한 설정을 하게된다.

시리얼 통신을 하기위한 순서는

1) CreateFile로 파일을 연다.
2) SetCommState함수로 통신포트의 설정을 한다.
3) ReadFile이나 WriteFile로 데이터를 송수신한다.
4) CloseHandle로 파일을 닫는다.


시리얼 통신을 하기위해서는 Windows에서는 HANDLE형의 변수로 파일등의 오브젝트를 구별하여 억세스나 조작을 하게 된다.
이 때 사용하는 시리얼 포트를 특정하기 위해서는 HANDLE형 변수가 필요하다.
다음으로 WinAPI에서는 시리얼 포트의 설정값을 다르는 구조체로서 DCB구조체를 사용한다.
또 시리얼 포트의 타임 아웃 설정값을 다루는 COMMTIMEOUTS구조체가 있다.

Posted by 띠리
BLOG main image
프로그래밍 공부하면서 써가는 개인 노트 (따라서 여기에 씌여있는 소스의 신빙성을 보장 못함 -.-;;) 이 블로그 보면서 틀린 점이 있으면 꼬옥 알려주세요. by 띠리

공지사항

카테고리

분류 전체보기 (323)
Win32 SDK 초보 (27)
통신관련 (11)
MFC TIP (20)
C/C++ TIP (10)
개발기타 (10)
링크 (2)
견물생심 (24)
이것저것 (8)
용어메모 (3)
데이터베이스 (32)
비주얼 베이직 (10)
하드웨어 (3)
C# (42)
Xcode (3)
델파이 (82)
홈페이지 (5)
MindStorm (0)
낙서 (5)
스크래치 (0)
기타 (6)
아두이노 (1)
라즈베리파이 (2)
안드로이드 (6)
파이썬 (0)
WEB (2)
Total : 977,901
Today : 71 Yesterday : 132