Published 2023. 6. 1. 00:02
728x90

동기화(Synchronization)가 필요한 이유 

두 개의 프로세스가 동일한 공유된 메모리에 접근. 

 - 프로세스는 서로 협동하여 규칙을 준수하며 사용 해야 한다.

 - 잘못된 연산을 없애고 일관성을 보장해야 한다. 

응용프로그램에서 동기화 방식

  •  Semaphore
  • MUTEX
  • Condition Variable<

이러한 기법을 통해서 잠금을 하여 한번에 한 스레드만 접근하도록 제한을 한다. 

 

세마포어 란? 

  • - 실행 중인 여러 태스크가 동기화 또는 상호 배제를 목적으로 획득하거나 반환할 수 있는 커널 오브젝트

세마포어의 필요성

  • - 여러 태스크가 동시에 동작하는 응용 프로그램에서 태스크 간의 동작을 동기화해야 한다. 
  • - 공유 자원에 접근하고자 하는 태스크가 독점적으로 자원에 접근할 수 있도록 관리할 수 있는 방법이 필요하다.

세마포어의 유형

  • 이진 세마포어 binary semaphores ( 0,1 을 사용합니다.)
  • 계수 세마포어 counting semaphores (예시- 원하는 만큼 공유 자원을 할당 할수 있다. 즉 5개를 주면 5,4,3,2,1에서 0이 되는 순간 자원을 다쓴 형태입니다. )

 

세마포어에 대한 연산 (값을 초기화 하거나 내리거나 올리거나 할수 있는 연산) 

  • nitialize (create)
  • wait (pend)
  • post (signal)

 

리눅스에서 세마포어의 형식

  • 이름 없는 세마포어 (Unnamed Semaphore)
    •    세마포어가 프로세스 메모리 내에 존재하기 때문에 스레드간에 사용하는 경우 전역변수를 사용
    •    프로세스간에 사용하는 경우는 공유메모리에ㅐ 세마포어를 만들어 줘야 함
  • 이름 있는 세마포어(Named Semaphore)
    • 세마포어가 파일 형태로 만들어지기 때문에 파일 이름만 알면 세마포어를 사용할 수 있음
    • 파일 이름은 최대 251문자 까지 가능
    • Kernal 버전 2.6.19부터는 /dev/shm/ 위치에 sem.[이름] 형태로 파일이 생성됨

 

세마포어의 동작 ! 

동작 

  • 태스크가 세마포어를 획득할 경우, 태스크는 원하는 동작을 수행하거나 공유 자원에 접근할 수 있다.
  • 태스크는 하나의 세마포어를 여러 번 획득할 수 있다. 
    • 이 횟수에는 제한이 있으며, 이 값은 세마포어를 생성할 때 결정된다.
    •   커널은 세마포어의 토큰 카운트 값을 통해서, 세마포어의 획득 횟수를 알 수 있다.     
  •  세마포어 카운트가 한계 값에 도달하면, 이미 세마포어를 획득한 다른 태스크가 바노할할 때까지 다른 태스크는 더 이상 세마포어를 획득할 수 없다. (즉 값이 0이 되었을경우) 
  • 토큰 카운트가 0이 되었다면, 세마포어를 요청한 태스크는 세마포어를 획득할 수 없으므로, 세마포어가 사용 가능해질 때까지 블록 상태대기하거나 세마포어 획득을 포기한다.
    • 세마포어 대기 리스트로 대기중인 태스크들을 관리한다.

 

세마포어 변수를 사용하는 스레드 : 

 

세마포어의 동작을 위한 변수 필요 :

sem Count = 1;

 

thread_with_critical_section() {

// critical_section 이란 단 한번만 접근해서 처리해야한다. 여러개가 접근하면 망가질수 있는 코드 사이에 세마포어를 넣어줘야합니다.

sem_wait(&sem);

Critical_section

sem_post(&sem);

}

 인 상태에서 첫번째 스레드(T1)일 실행되는 동안 스레드2(T2)가 접근하면 sem sleep queue을 줘서 잠시 대기 상태로 만들어 놓습니다.

sem_post인 상태에서 값이 0에서 1이 되어버리면 sem sleep에 있던 값들을 (한번에) ready queue에 넣고 우선 순위 높은것을 고른 후에 진행을 하게 됩니다. 

 

예시)

더보기

 sem Count =3이면 t1,t2,t3가 한번에 들어가서 실행을 할수 있습니다. 

 

세마포어 변수를 사용 하는 스레드 

- 접근한 순서는 T1 -> T2 -> T3 순이다.

- 우선순위는 T3 ->T2 ->T1 순이다.

- 초기화 된 세마포어 변수 sem을 T1, T2, T3 각 3개의 스레드가 잠그려 하는 상황이다.

- 세마포어를 잠글 때에는 sem_wait() 함수를, 풀어줄 때에는 sem_post() 함수를 사용한다.

- T1이 sem을 잠그면서 sem의 count를 하나 감소시킨다. count가 0이 되면 이후 이 세마포어를 잠그려는 스레드는 block되게 한다.

- T1의 상호 배제 구역 수행 중에 sem을 잠그려 한 T2와 T3는 sem의 sleep queue에 들어가 block 된다.

- T1이 sem을 풀면서 sem의 count를 하나 증가시키고 sleep queue에 block 되어 있던 T2 와 T3를 read queue로 넣어준 후 return 한다.

 상호배제 문제

- 세마포어는 아무 스레드나 post가 가능하기 때문에 critical section을 보호하기 위해 사용하는 경우 잘못 사용하면 상호배제(mutual exclusion)를 보장할 수 없을 수도 있으므로 주의해야한다.

 

post가 가능하기 때문에 잘못사용을 하면 상호 배제를 보장하지 못하고 sem_post를 여러 번 한것같이 될수 있습니다.

즉 소유의 개념이 없습니다.

 

실행 순서 동기화

- 실행 순서 동기화를 목적으로 세마포어를 사용하면 초기값을 0으로 해야합니다.

a 와 b 중에 b를 실행할때 뒤에 실행 시켰다고 하더라도 값이 0이라면 block처리가 되고 a가 값을 처리하고 b를 처리하게 됩니다.

0으로 세탕하고 순서를 맞춰줄수 있습니다.

728x90
복사했습니다!