BLOG ARTICLE 시그널 | 1 ARTICLE FOUND

  1. 2007.12.28 OS분석(4) picoKernel

OS분석(4) picoKernel

OS 2007. 12. 28. 14:01
3. IPC
IPC(Inter Process Communication)는 프로세스간 상호 통신을 말한다.
구현방법에서 크게 두가지 방법으로 나눌수 있는데 하나는 공유 메모리이고 두번째는 메시지 전달 방식이다.

공유메모리 방식은 송신측과 수신측이 일정한 메모리 공간을 공유하고 송신측이 이 공간에 데이터를 쓰면 수신측이 읽어 가는 형태이다.
공유 메모리 방식의 동기화를 위해서는 수신측은 송신측이 데이터를 기록하였는지 알아야 하고 송신측은 수신측이 데이터를 읽어갔는지 여부를 알아야 하며 이를 활용하는 프로그래머는 적절한 동기화 절차를 거쳐야 한다.
데이터를 바로 읽어가기 때문에 오버헤드가 크지 않기 때문에 큰 데이터를 전달할 때 유용하지만 동기화문제를 신경써야한다.

메시지 전달 방식은 운영체제가 커널 내부에서 메시지를 기록할 수 있는 공간을 두고 적절한 시스템 콜을 통해 메시지의 송수신을 운영체제에게 요구할 수 있도록 하는 방식이다. 즉 커널이 메시지를 받아 전달시켜주는 방식이다. 대표적인 예가 메일박스이다. 이 방식의 동기화의 경우 메시지를 위한 공간이 꽉 찼을 경우 송신측이 대기하여야 하고 반대로 비어있을 경우 수신측이 대기해야한다. 메시지를 커널로 복사하고 이 메시지를 다시 수신측에게 복사해야하므로 오버헤드가 큰 대신 동기화에 대한 문제를 크게 신경쓰지 않아도 되어서 메시지 양이 작은 경우 사용하면 유용하다.

picoKernel에는 프로세스간 통신을 위해 메일박스, 랑데부, 시그널이 구현되어 있다.

3.1 메일박스
메일박스는 메시지 전달방식으로 내부에 버퍼를 두고 송신측이 이 버퍼에 데이터를 전달하고 수신측이 이 버퍼에서 데이터를 받아가는 형식으로 되어 있다.
메일박스의 엔트리를 보면 해당 메일박스가 비어있는지 차있는지에 대한 세마포어와 순환 버퍼의 시작과 끝을 가르키는 인덱스, 메시지 버퍼(순환 버퍼)로 구성되어 있다. 또한 메일박스를 사용하기 위한 뮤택스와 사용하고 있는 메일박스의 엔트리 개수를 나타내는 변수가 있다.

메일박스의 생성은 mboxCreate이고 초기화시 메일박스 테이블에 대한 초기화, 해당 메일박스가 비어있는지 꽉차있는지를 확인하고 기다리는 세마포어의 초기화 후 메일박스의 id를 리턴한다.

mboxSend는 메시지를 전송하는 함수이다. 매개변수로 메일박스의 id와 메시지에 대한 포인터를 받는다.
메시지를 전달할 때 세마포어를 통해 메시지 버퍼가 비어있기를 대기한다. 메시지가 비어있게 되면 메시지를 버퍼 공간에 쓰기 위해 뮤택스로 락을 걸어두고 메시지를 저장후 버퍼공간의 헤드와 테일 인덱스를 업데이트 한다. 락을 해제한 후 수신측이 읽어도 된다고 세마포어를 통해 시그널을 보낸다.

mboxRecive는 메시지를 수신하는 함수이며 마찬가지로 매개변수를 id와 메시지를 받을 포인터를 받는다.
메시지가 저장되었다는 세마포어의 시그널을 기다렸다가 시그널이 오면 뮤택스로 락을 걸고 데이터를 읽어온다. 헤드 인덱스를 초기화 한 다음 뮤택스 락을 해제한 후 버퍼가 비었다는 세마포어의 시그널을 보내 다음 메시지가 버퍼에 저장될 수 있도록 한다.

3.2 랑데부
랑데부는 극단적으로 버퍼가 0인 통신이다. 말 자체로 송신측과 수신측이 만나서 데이터를 전달 받는 형식이다. 메일박스가 내부의 버퍼를 두고 통신을 하는데 반해 랑데부는 버퍼 없이 송신측이 수신측으로 바로 데이터를 전달한다.

메일박스와 비슷하게 rendCreate, rendSend, rendRecive로 구성되어 있다. 랑데부의 엔트리는 송신측과 수신측의 thread id, 대기와 완료를 알리는 세마포어, 메시지로 구성되어 있다.

랑데부를 생성하게 되면(rendCreate), 송신측과 수신측의 thread 번호를 등록하고 세마포어를 초기화한 후 랑데부 아이디를 리턴한다.

rendSend는 랑데부 id와 메시지를 매개변수로 받고 수신측이 대기상태가 될때까지 세마포어를 통해 기다린다. 수신측 대기상태의 세마포어 시그널을 보내면 메시지를 복사하고 완료했다는 세마포어 시그널을 보낸다.

rendRecive 역시 id와 메시지를 저장할 공간을 매개변수로 받아 포인터를 연결시킨다음 대기상태라는 세마포어 시그널을 송신측에 보내 데이터를 전달 받은 다음 완료했다는 세마포어 시그널을 보낸다.

3.3 시그널
시그널이 구현되기 위해서는 thread control block에 시그널 번호별로 해당 핸들러 함수를 등록해야하고 초기화시 0으로 세팅한다.

signalSet함수는 시그널 번호에 따른 핸들러 함수를 등록시키는 함수이고 signalSend는 시그널을 보내는 함수이다. signalSend함수를 호출해서 해당 핸들러가 성공적으로 호출되었으면 1로 설정되어있던 비트를 다시 초기화 시켜준다.

해당 스레드가 running상태가 아니라면 running가 된 후 즉 문맥교환이 이루어진 후에 시그널이 왔는지를 확인해야한다.


AND