학교수업

시스템 프로그래밍 - 랩핑함수의 제작

3년안에 내집 마련 2019. 6. 4. 00:25
반응형

 - 라이브러리용 랩핑 함수 sysv_semget토큰이나 키값, 세마포어 개수, 초기화할 semval 초기값, 접근모드 입력시 세마포어의 IPC 값 반환

 - 만약 세마포어가 생성되지 않으면 생성하고 초기화

 - IPC ID가 이미 존재시 errno == EEXIST를 내고 기존의 세마포어 IPC ID를 알려줌(ID를 초기화하지는 않는다.)

 

세마포어 생성 라이브러리 함수

int sysv_semget(char *tok, key_t sem_fixkey, int n_sem, int sem_value, int user_mode)
{
	int	sem_id, i;
	union semun semun;
	unsigned short int *arr_semval = NULL;
	key_t	sem_key;

	/* if tok is not NULL, we make IPC key for semaphore */
	if (tok != NULL) {
		if ((sem_key = ftok(tok, 1234)) == -1) {
			return -1;
		}
	} else {
		sem_key = sem_fixkey;
	}
	if ((sem_id = semget(sem_key, n_sem, IPC_CREAT|IPC_EXCL|user_mode)) == -1) {
		if (errno == EEXIST) {
			sem_id = semget(sem_key, 0, 0);
			return sem_id;
		}
	}
	if (sem_id == -1) {
		fprintf(stderr,"FAIL: semget [%s:%d]\n", __FUNCTION__, __LINE__);
		return -1;
	}

	/* init semaphore value */
	if ((arr_semval = (unsigned short int *) malloc(sizeof(unsigned short int) * n_sem)) == NULL) {
		fprintf(stderr, "FAIL: malloc [%s:%d]\n", __FUNCTION__, __LINE__);
		return -1;
	}
	for(i=0; i<n_sem; i++) arr_semval[i] = sem_value;
	semun.array = arr_semval;
	if (semctl(sem_id, 0, SETALL, semun) == -1) {
		fprintf(stderr, "FAIL: semctl [%s:%d]\n", __FUNCTION__, __LINE__);
		free(arr_semval); arr_semval = NULL;
		return -1;
	}
	free(arr_semval);
	return sem_id;
}

간략적인 해석

1. int sysv_semget(char *tok, key_t sem_fixkey, int n_sem, int sem_value, int user_mode)

-> semget함수 호출시 사용자로부터 키값, 세마포어 개수, semval 초기값, 접근모드를 입력받음

 

2. if (tok != NULL) {
      if ((sem_key = ftok(tok, 1234)) == -1) {
         return -1;
}

-> tok != null이면  ftok 함수를 통해 IPC키을 생성한다.

    ftok함수시 return 값이면 -1이면 실패

 

3. else {
   sem_key = sem_fixkey;

-> tok == null이면 직접 IPC 키를 입력받는 경우이므로 sem_fixkey를 IPC키로 사용 

 

4. if ((sem_id = semget(sem_key, n_sem, IPC_CREAT|IPC_EXCL|user_mode)) == -1) {
     if (errno == EEXIST) {

->  errno ==EEXIST -> 이미 IPC 아이디 존재하면 IPC_EXCL에 의해 EEXIST에러를 보냄

 

5. sem_id = semget(sem_key, 0, 0);
   return sem_id; 

-> IPC_ID가 존재하는 경우 IPC_ID를 알아내기 위해 semget(id,0,0)을 호출

 

6. if ((arr_semval = (unsigned short int *) malloc(sizeof(unsigned short int) * n_sem)) == NULL) {

-> 세마포어를 할당받았을 경우 힙 메모리를 동적할당 받고 전체 배열을 setall로 초기화함 그 후 사용자가 초기 세마포어 값(sem_value) 초기화

 

7.  semun.array = arr_semval; 

    if (semctl(sem_id, 0, SETALL, semun) == -1) 

-> 앞에서 할당한 힙 영역의 주소를 semun,array에 전달 -> semctl에 넘겨줌

 

세마포어 세트 삭제 랩핑함수(sysv_senrm)와 특정위치 세마포어 값 읽어오는 함수(sysv_semval)

int sysv_semrm(int sem_id)  // 세마포어 삭제
{
	if (semctl(sem_id, 0, IPC_RMID) == -1) {  // 세마포어 세트를 삭제하는 것이 실패하면
		fprintf(stderr, "FAIL: semctl() 'IPC_RMID' [%s:%d]\n", __FUNCTION__, __LINE__);  // 에러를 띄운다.
        
		return -1;
	}
	return 0;  // 정상 = 0 비정상 = -1
}

int sysv_semval(int sem_id, int sem_idx)  // 특정 위치의 세마포어 값 읽어오기
{
	int	semval;
	if ((semval = semctl(sem_id, sem_idx, GETVAL)) == -1) {  // sem_idx : 읽어올 코드 위치, 읽어오는 것 실패하면) 
		fprintf(stderr, "FAIL: semctl() 'GETVAL' [%s:%d]\n", __FUNCTION__, __LINE__);  //에러코드 띄운다.
		return -1;   
	}
	return semval;  // 에러 = -1 정상 = 특정위치 세마포어 값
}

 

반응형