간단하게 리소스 카운터라고 생각해도 되는데 일단은 데드락 피하기 위한

기술 중의 하나라고 한다..

실제 어디다 써먹을지는 아직 모르겠지만.. 이거보다는 개인적으로 뮤텍스를 더 자주 쓰는듯 싶네..

 

소스코드 출처 : http://forum.falinux.com/zbxe/?document_srl=428639

 

int semget ( key_t key, int nsems, int semflg )

세마포어 식별자를 가지고 오는 함수다.

 

key_t key

시스템에서 세머포어를 식별하는 키 번호

int nsems

세마포어 집합 내의 세마포어 개수로 접급 제한하려는 세마포어 자원의 개수

int semflg 동작 옵션 ( IPC_CREATE와 IPC_EXCL이 있다.)

 

 

int semctl ( int semid, int semnum, int cmd, union semun arg)

세마포어를 control 하는 함수다.

 

int semid 시스템에서 세머포어를 식별하는 집합 번호
int semnum

세마포어 집합 내에서의 세마포어 위치 (세마포어 넘버...)

int cmd

제어 명령( 값을 설정, 삭제, 소유권, 등등 많다.)

union semun arg 위의 제어명령 cmd 에 따라 달라진다., 설정 또는 값을 구하는 변수 
union semun{
   int                  val;
   struct   semid_ds   *buf;
   unsigned short int  *arrary;
}

int semop ( int semid, struct sembuf *sops, unsigned nsops )

세마포어의 값을 변경한다. 값을 증가, 감소시킨다.

 

int semid 시스템에서 세머포어를 식별하는 집합 번호
struct sembuf *sops

세마포어 값을 계산하기위한 설정 값 
struct sembuf {
    short sem_num;   세마포어 번호
    short sem_op;     세마포어 증감값
    short sem_flg;     옵션 
}

unsigned nsops

변경하려는 세마포어 개수로 변경하려는 세마포어 개수가 여러 개일 때 사용
n개의 세마포어 옵션들..

 

 

예제를 봐야 이게 뭔지 조금은 이해가 간다.

매우간단한 멀티 쓰레드 구조의 카운터다.

failinux.com.. 참 괜찮다.

 

 

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

#include 
#include 
#include 
#include 
#include "sys/ipc.h"
#include "sys/sem.h"
#include "sys/poll.h"

int         cnt   = 0;
static int  semid;

void semop1() 
{
    struct sembuf buf1;

    buf1.sem_num   = 0;
    buf1.sem_op    = -1;
    buf1.sem_flg   = SEM_UNDO;

    if (semop(semid, &buf1, 1) == -1)
        printf( "%s::semop() Fail\n", __func__);
}

void semop2()
{
    struct sembuf buf2;

    buf2.sem_num   = 0;
    buf2.sem_op    = 1;
    buf2.sem_flg   = SEM_UNDO;

    if (semop(semid, &buf2, 1) == -1)
        printf( "%s::semop() Fail\n", __func__);
}

void *fun_thread1(void *arg) {
    while( 1) {
        semop1();
        printf( "thread1 run \n");
        if ( 5 < cnt) {
            printf( "thread1 Completely terminated \n");
            semop2();
            break;
        }
        else {
            cnt++;
            poll(0,0,100);
            printf( "thread1 terminated \n");
        }
        semop2();
    }
    return;
}

void *fun_thread2(void *arg)
{
    while( 1) {
        semop1();
        printf( "thread2 run \n");
        if (5 < cnt) {
            printf( "thread2 Completely terminated \n");
            semop2();
            break;
        }
        else {
            printf( "=====>>Counter= %d\n", cnt);
            poll(0,0,100);
            printf( "thread1 terminated \n");
        }
        semop2();
    }

    return;
}

int main(int argc, char *argv[])
{
    pthread_t thread1;
    pthread_t thread2;
    union semun{
        int                  val;
        struct   semid_ds   *buf;
        unsigned short int  *arrary;
    }arg;

    if ((semid = semget( IPC_PRIVATE, 1, IPC_CREAT| 0666)) == -1) {
        printf( "semget() Fail\n");
        return -1;
    }

    arg.val=1;                // Semaphore value = 1
    if (semctl(semid, 0, SETVAL, arg) == -1) {
        printf( "semctl()-SETVAL Fail\n");
        return -1;
    }

    pthread_create(&thread1, NULL, fun_thread1, NULL);
    pthread_create(&thread2, NULL, fun_thread2, NULL);
    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);

    if (semctl(semid, 0, IPC_RMID, arg) == -1) {
        printf( "semctl()-IPC_RMID Fail\n");
        return -1;
    }
    printf( "Process Terminated!");
    return 0;
}
/* The end of function */
# 수행결과는 다음과 같다.
./a.out
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 1
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 2
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 3
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 4
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
=====>>Counter= 5
thread1 terminated 
thread1 run 
thread1 terminated 
thread2 run 
thread2 Completely terminated 
thread1 run 
thread1 Completely terminated 

 

 

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

 

failinux 그대로 가져왔슴..

개인적인 테스트용이므로,, 저작권에 문제가 있다면

알려주시길.. 지우던지 다른 방식으로 구현해두겠습니다.

반응형

'Language > C' 카테고리의 다른 글

select 함수 예제  (167) 2012.07.23
Unix Domain Socket 예제  (165) 2012.07.23
mmap / munmap 함수 예제  (12) 2012.07.17
shmget/ shmat 함수 예제  (8) 2012.07.13
C FAQ (포인터 증가 3)  (155) 2012.07.13
파일이나 디바이스를 주소 공간 메모리에 대응시키는 방식인데

일종의 IPC 통신으로 사용가능하다. 매우 빠름.

 

출처 : 소스코드 http://www.cs.purdue.edu/homes/fahmy/cs503/mmap.txt

 

void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);

파일이나 디바이스를 응용 프로그램의 주소 공간 메모리에 대응시킨다.

 

1인자 => 시작 포인터 주소 (아래의 예제 참조)

2인자 => 파일이나 주소공간의 메모리 크기

3인자 => PROT 설정 (읽기, 쓰기, 접근권한, 실행)

4인자 => flags는 다른 프로세스와 공유할지 안할지를 결정한다.

5인자 => fd는 쓰거나 읽기용으로 열린 fd값을 넣어준다.

6인자 => offset은 0으로 하던지 알아서 조절한다.

 

int munmap(void* start, size_t length);

할당된 메모리 영역을 해제한다.

 

1인자 => 위에 mmap으로 지정된 포인터값 넣어주고

2인자 => 위에서 사용했던 length와 동일하게 넣어준다.

(왜냐면.. 할당했던거 동일하게 해제해야 하니깐..)

 

더 자세한 사항은 man page에 모든게 나와있음.

 

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

#include 
#include 
#include 
#include 
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/mman.h" /* mmap() is defined in this header */

int main (int argc, char *argv[])
{
    int fdin, fdout;
    char *src, *dst;
    struct stat statbuf;

    if (argc != 3) {
        printf("usage: a.out  \n");
        return -1;
    }

    /* open the input file */
    if ((fdin = open (argv[1], O_RDONLY)) < 0) {
        printf ("can't open %s for reading", argv[1]);
        return -2;
    }
    /* open/create the output file */
    if ((fdout = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) < 0) {
        printf ("can't create %s for writing", argv[2]);
        return -2;
    }

    /* find size of input file */
    if (fstat (fdin,&statbuf) < 0) {
        printf ("fstat error");
        return -2;
    }

    /* go to the location corresponding to the last byte */
    if (lseek (fdout, statbuf.st_size - 1, SEEK_SET) == -1) {
        printf ("lseek error");
        return -2;
    }

    /* write a dummy byte at the last location */
    if (write (fdout, "", 1) != 1) {
        printf ("write error");
        return -2;
    }
    /* mmap the input file */
    if ((src = mmap(0, statbuf.st_size, PROT_READ,
                    MAP_SHARED, fdin, 0)) == (caddr_t) -1)
    {
        printf ("mmap error for input");
        return -2;
    }

    /* mmap the output file */
    if ((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE,
                    MAP_SHARED, fdout, 0)) == (caddr_t) -1)
    {
        printf ("mmap error for output");
        return -2;
    }

    /* this copies the input file to the output file */
    memcpy (dst, src, statbuf.st_size);

    munmap(src, statbuf.st_size);
    munmap(dst, statbuf.st_size);

    return 0;
} /* main */
/* The end of function */
실행 후 결과 화면 
$ ./a.out test test_out
$ ls -al
drwxr-xr-x  2 jeon jeon 4096 Jul 17 08:39 .
drwx------ 12 jeon jeon 4096 Jul 17 08:39 ..
-rwxr-xr-x  1 jeon jeon 6410 Jul 17 08:39 a.out
-rw-r--r--  1 jeon jeon 1844 Jul 17 08:39 mmap.c
-rw-r--r--  1 jeon jeon  469 Jul 17 08:29 test
-rw-------  1 jeon jeon  469 Jul 17 08:39 test_out

 

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

 

test라는 입력파일은 미리 생성하고

test_out은 위의 프로그램을 실행하고 생성된 파일이다.

생각보다 간단한것 같은데.

최대 어느정도까지 매핑시키는지는 추후에 해봐야겠다..

반응형

'Language > C' 카테고리의 다른 글

Unix Domain Socket 예제  (165) 2012.07.23
semget. semop, semctl 함수 예제  (14) 2012.07.17
shmget/ shmat 함수 예제  (8) 2012.07.13
C FAQ (포인터 증가 3)  (155) 2012.07.13
nmemb 의미  (153) 2012.07.12

출처.: http://www.falinux.com/


IPC의 시작인 메시지큐 통신이다.

 

       int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

 

int msqid

메시지 큐  식별자 , msgget 함수의 리턴값이다.

void *msgp

전송할 자료, void 포인터니까 아무 자료형이나 덮어쓰면된다.

size_t msgsz

전송할 자료의 크기, 자료가 구조체건 뭐건 sizeof로 정확한 크기면 된다.

int msgflg

동작 옵션, 큐에 공간이 있을떄까지 기다리면 0, 여유공간 없으면 복귀 시킬경우, IPC_NOWAIT.

 

 

       ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                      int msgflg);

 

int msqid

메시지 큐 식별자, msgget 함수의 리턴값.

void *msgp

전송할 자료, 마찬가지로 아무 자료형이나 선언하기 나름.

size_t msgsz

전송할 자료의 크기, 위에 선언한거에 그냥 sizeof로 정확한 사이즈로 기재하면되고

logn msgtyp

int msgflg

수신할 메시지 타입, 0이면 다 받고 0보다 크면 큐에 가장 처음 메시지에서 타입이 같은거만 받고

동작 옵션

--------------------------------------------------------------------------

=== 메시지 수신하는 코드 ===
#include 
#include 
#include 
#include "sys/types.h"
#include "sys/ipc.h"
#include "sys/msg.h"

#define  BUFF_SIZE   1024
#define  KEY   35002

typedef struct {
    int   msgid;
    long  type;
    char  buff[BUFF_SIZE];
} t_data;

int main()
{
    int      msqid;
    t_data   data;

    printf("t_data size = %d\n", sizeof(t_data));
    printf("long size = %d\n", sizeof(long));

    if (( msqid = msgget( (key_t)KEY, IPC_CREAT|0666)) == -1) {
        perror( "msgget() fail");
        return -1;
    }

    while(1)
    {
        /* IPC message recv */
        if(msgrcv(msqid, &data, sizeof(t_data)-sizeof(long), 1, 0) == -1)
        {
            perror( "msgrcv() fail");
            return -2;
        }
        printf( "ID=[%d] MSG => %s\n", data.msgid, data.buff);
    }

    return 0;
}
/* end of the program */
===수신측 결과=== 
ID=[1] MSG => msg_type=0,index=1, message queue program
ID=[1] MSG => msg_type=10,index=11, message queue program
=== 메시지 송신하는 코드 ===
#include 
#include 
#include 
#include 
#include "sys/types.h"
#include "sys/ipc.h"
#include "sys/msg.h"
#include 

#define  BUFF_SIZE   1024
#define  KEY         35002

typedef struct {
    int   msgid;
    long  type;
    char  buff[BUFF_SIZE];
} t_data;

int main()
{
    int      msqid;
    int      index   = 0;
    int      ret   = 0;
    t_data   data;

    printf("t_data size = %d\n", sizeof(t_data));
    printf("long size = %d\n", sizeof(long));

    if((msqid = msgget((key_t)KEY, IPC_CREAT|0666))== -1) {
        perror( "msgget() Fail");
        return -1;
    }

    while(1)
    {
        data.type  = index;
        data.msgid =  ((index++ %10)+1);

        sprintf( data.buff, "msg_type=%ld,index=%d, message queue program",
                data.type, index);

        printf( "ID=[%d]  MSG => %s\n", data.msgid, data.buff);

        /* IPC message send */
        ret = msgsnd(msqid, &data, (sizeof(t_data)-sizeof(long)), 0);
        if(ret == -1)
        {
            perror( "msgsnd() Fail");
            return -2;
        }
        /* sleep 2 seconde */
        poll(0, 0, 2000);
    }
    return 0;
}
===송신측 결과 ===
ID=[1]  MSG => msg_type=0,index=1, message queue program
ID=[2]  MSG => msg_type=1,index=2, message queue program
ID=[3]  MSG => msg_type=2,index=3, message queue program
ID=[4]  MSG => msg_type=3,index=4, message queue program
ID=[5]  MSG => msg_type=4,index=5, message queue program
ID=[6]  MSG => msg_type=5,index=6, message queue program
ID=[7]  MSG => msg_type=6,index=7, message queue program
ID=[8]  MSG => msg_type=7,index=8, message queue program
ID=[9]  MSG => msg_type=8,index=9, message queue program
ID=[10]  MSG => msg_type=9,index=10, message queue program
ID=[1]  MSG => msg_type=10,index=11, message queue program
ID=[2]  MSG => msg_type=11,index=12, message queue program

 

--------------------------------------------------------------------------

위에 보면 10으로 나눈 나머지에서 1이 되는 경우에만 수신하도록 구현되어 있다.

 

가장 중요한 부분은

메시지 사이즈 부분에 sizeof(long)만큼을 뺴주었는데

그 이유는 아래와 같다...

전에 이거 몰라서 찾는데 일주일 날린것만 생각하면.. 치가 떨린다...

 

struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};

The mtext field is an array (or other structure) whose size is specified by msgsz, a nonnegative integer value.


반응형

'Language > C' 카테고리의 다른 글

C FAQ (포인터 증가 3)  (155) 2012.07.13
nmemb 의미  (153) 2012.07.12
C FAQ (포인터 증가 2)  (7) 2012.07.12
C FAQ (포인터 증가에 대해서)  (7) 2012.07.12
C-FAQ 어찌되었건 pointer 쓰면 정말 좋은가?  (7) 2012.07.12

+ Recent posts