스레드 생성: 싱글 스레드는 함수1 수행 후 함수2를 수행하는 순차적인 형식이다. 멀티스레드는 스레드를 함수 단위로 구현한다. 함수1, 함수2를 pthread_create()
와 같은 시스템 콜의 인자로 넘겨줘서 스레드를 생성해서 병렬적으로 동작하는 것처럼 구현한다. 2개의 함수의 스레드를 만들면 메인 스레드를 포함해서 3개의 스레드가 존재하는 것이다. 보통 멀티스레드 환경에서는 스레드로 만들 함수들을 무한 루프로 구현한다. pthread
는 POSIX 표준을 따르는 스레드와 관련된 라이브러리이다. pthread_create
, pthread_exit
, pthread_join
등의 함수가 존재한다. join
은 멀티프로세스에서 동기화를 위해 사용한 wait
과 동일하다.
차이점: 코드 세그먼트와 데이터 세그먼트, 파일 I/O는 스레드끼리 공유해서 사용하지만, 특정 함수를 스레드로 만드는 것이므로 스레드별로 다른 데이터를 관리하기 위해서 스택을 따로 가지고 있다. 코드 섹션은 공유하지만 수행되어야 하는 instruction의 위치가 다르기 때문에 레지스터 값과 스택 포인터의 값도 스레드별로 다르다. 즉, 스레드마다 레지스터 정보와 스택 영역은 독립적이다.
주소 공간: 코드 세그먼트, 데이터 세그먼트, 힙은 공유하고 스택 위에서부터 스레드가 쌓인다. 스레드 사이에는 가드 영역이 존재하고 운영체제가 그 크기를 지정한다. 각각의 스레드가 수행되다가 멈췄을 때의 context를 스택이나 커널 단에 저장해서 관리한다.
예시:
fork
로 새 프로세스를 생성해서 request를 처리했으나 단순한 작업을 위해서는 overkill이다. 자식 프로세스에서 하던 작업을 함수로 만들고 request가 올 때마다 스레드를 새로 생성해서 request를 처리하도록 하면 동일하게 동작한다. 멀티 프로세스에서는 부모 프로세스가 소켓 연결을 끊고 다시 request를 기다리는데, 스레드에서는 한 프로세스 내에서 소켓을 유지해야 하므로 처리가 끝났을 때 소켓을 닫는다. 멀티 프로세스를 이용하는 예시로는 리눅스 아파치가 있다. 윈도우는 IIS라는 웹서버가 채택되어 있는데 스레드 개념이 나온 이후의 운영체제이기 때문에 유닉스와 달리 프로세스 간 부모-자식 개념이 없어서 멀티 프로세스로 구현되어 있지 않다.setup
함수를 한 번 수행하고 loop
함수를 반복 수행한다. 멀티태스크 작업할 때는 보통 루프를 비워놓는다. xTaskCreate
함수를 통해서 Task를 인자로 주고 스레드를 생성하면 동시에 동작하는 것처럼 수행된다.싱글 프로세스/멀티 프로세스/멀티 스레드 비교: DoCmd
함수를 수행하는 형태를 비교한다.
DoCmd
함수를 수행하면 함수 수행이 끝날 때까지 다음 작업을 수행할 수 없다.fork
하면 새로운 프로세스가 생성되고 부모는 wait
을 통해서 기다리다가 자식이 exit
을 수행하면 시그널을 받아서 wait
상태에서 빠져나오고 다시 while 루프가 수행된다.pthread
를 이용한다. pthread_t
는 프로세스에서 PCB와 같은 역할을 수행하는 스레드 정보를 저장할 수 있는 구조체이다. 구조체를 pthread_create
의 첫 번째 인자로 전달하고 두 번째 인자는 스레드의 Attribute를 설정하는 것인데 null로 하면 디폴트 상태로 생성된다. 세 번째 인자로 스레드 형태로 수행할 함수를 void 포인터 형태로 넣어주고, 네 번째는 함수를 수행하기 위한 파라미터이다. 파라미터는 포인터 변수여야 하고 하나만 전달 가능하기 때문에 구조체를 많이 사용한다.#if
조건이 0이면 #endif
까지의 코드를 수행하지 않고 1이면 수행하도록 conditional compilation 한다. 디버깅할 때 많이 쓰는 기능으로 주석을 추가했다가 삭제할 필요 없이 디버그 모드는 1, 릴리즈 모드는 0으로 처리한다.pthread
라이브러리가 해당한다.