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

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

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

 

소스코드 출처 : 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 함수 예제  (0) 2012.07.23
Unix Domain Socket 예제  (0) 2012.07.23
semget. semop, semctl 함수 예제  (0) 2012.07.17
mmap / munmap 함수 예제  (0) 2012.07.17
shmget/ shmat 함수 예제  (0) 2012.07.13
C FAQ (포인터 증가 3)  (0) 2012.07.13

출처.: 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)  (0) 2012.07.13
nmemb 의미  (0) 2012.07.12
msgsnd/ msgrcv 함수 예제  (0) 2012.07.12
C FAQ (포인터 증가 2)  (0) 2012.07.12
C FAQ (포인터 증가에 대해서)  (0) 2012.07.12
C-FAQ 어찌되었건 pointer 쓰면 정말 좋은가?  (0) 2012.07.12

+ Recent posts