[yummyHitOS] 19 day (2017.08.05)

5 분 소요

오랜만이에영!! 요즘 넘나 글을 못쓰고 있지여ㅜㅠ 죄송해여... 한 가지 문제점을 아직도 못찾아서... GUI환경으로 넘어갔을 때 웨웨웨 마우스 포인터 범위를 잘못 읽는 거신지...ㅜㅠㅜ 머리가 참 안돌아가네영



웨저뤱! 외않되! 끼야아아임므아아아앙...
멘탈잡아야져 ㅜㅠ늉늉 참 며칠전에 HDCON CTF대회가 있었는데... 미니언즈 banana문제를 2시간만에 겨우 풀었음에도 4시간동안 답이 틀려서... 나중에 알고보니 hdcon{flag} 형식이 아닌 그냥 flag 입력이었다는군녀 ㅜㅠ보통 ctf에서는 대회명{플래그} 양식으로 사용하거든여...



Success를 띄웠는데 왜 답을 맞추질 못하니!! 바나나만 먹으면 뭐하니!! 후욱...후욱... 참 이건 올리디버거라는 환경인데여~(야미님 왜 오늘 21장 포스팅이 아닌 다른얘기만 계속 하시는거져? 반성하세여!! 넵... 얼른 끝낼게여... 사실 오늘 포스팅의 주제가 멀티쓰레딩이라 이미 Thread와 Process할 때 설명이 다 되었거든여ㅜㅠ) 제가 그냥 BIOS처럼 이쁘게 꾸몄어여 헿헿헤헤헿 YummyHitOS도 바이오스같더니 이것조차... 이정도면 변태인증각?!


마지막으로 다른얘기하자면 99nerds 오픈소스 후원 프로젝트에서 스티커를 구입해써여!!! C언어와 리버싱 등의 스티커는 없어서 제가 사용하는 것들인 Linux 펭귄 / GNU 황소 / Ubuntu / Vim / Qt 를 구매했더니 JetBrains사의 스티커를 더 주시더라구여!! 이렇게 혜자스러울수가!! 구입하는 경로를 알려드릴게여!!

http://www.99nerds.io



제가 페이스북을 통해서 구매를 했는데, Yummy라고 와서... 등기 찾으러 갔을 때 좀 난처했었다능...
해외에서는 노트북에 붙은 스티커를 통해 자신의 경력 및 특기를 인증한다고 해여! 그래서 전 제가 사용하는 것만 붙였어여!!


여기까지 여담! 그런데 여담치곤 너무 길지않나여? 이정도면 거의 네이버 블로그의 '낙서장' 게시판같네여 죄송해여...
15일차에서 다뤘던 태스크(Task)!! 기억하시나여!?!? 그 때 Process와 Thread와 Task의 차이가 불분명해서 열씸히 싸우듯이 설명해드렸었는데!!! 기억나시나여!!!


그 때 Thread와 함께 Multi Tasking / Multi Processing도 설명드렸었었었죠!! 그럼 오늘은 뭘해야할까요... 먼저 책의 내용을 보며 포스팅 한 후 추가적으로 필요한 부분에 대해 파고들어보아여!! ㅜㅠ 준비성 없는 놈이라 넘나 죄송해여...


Thread / Process

쓰레드(Thread)는 프로세스(Process) 내에서 실행되는 흐름의 단위라고 15일차에서 설명했었는데, 이 쓰레드가 여러 개로 동작하면 멀티 쓰레드겠지요!? 한 개의 Process 내에서 여러 개의 Thread를 통해 분산 작업을 할 수 있는데, Microsoft의 Windosw에서 메모장(Notepad) 같은 경우 20개 가량의 Thread를 사용한다고 해요! 나닛!? 고작 그 조그마한 메모장이 쓰레드를 20개씩이나?!

메모장의 구성을 보면 제목표시줄, 메뉴표시줄, 파일탭, 편집탭, 서식탭, 보기탭, 도움말탭, 최소화버튼, 최대화버튼, 닫기버튼, 편집창, 스크롤바, 각 탭의 각 메뉴들... 이 모든 것을 각 각 하나의 Thread로 돌려 모든 것이 다 만들어졌을 때 하나의 메모장으로 탄생하는 것이지요!

메모장으로 예를 들면 조금 더 이해가 잘 와닿더라구여!! 저만그런가여? 늉늉..



위 사진의 좌측 사진에서 보여주는 단일 쓰레드(Single Thread) / 멀티 쓰레드(Multi Thread)는 한 개의 프로그램을 실행시켰을 때 code, data, files 영역은 그대로 있고 Thread마다 각 Stack과 Register가 할당되어진 것을 볼 수 있으며 그것을 한 개의 프로세스에서 메모리 상으로 보여준 사진이 우측 사진이예요. 각 쓰레드는 자신의 고유 스택을 가지고 있지만, 실제 메모리에 대해 코드영역과 힙영역을 공유하여 사용할 수 있다는 것!!! 그렇기에 이 전 포스팅(18일차))에서 말씀 드린 것과 같은 임계영역이 필요하게 된 것이구요!


포스팅하다보니 오늘 설명드릴 부분이 정녕 전부 이 전에 다 설명드린 것들이네요... 그렇타면 다른 내용으로 넘어가보도록하져!!


user / kernel

Thread에는 User Level Thread(사용자 영역 쓰레드)와 Kernel Level Thread(커널 영역 쓰레드)가 있어요.

User Level Thread는 사용자 영역에서(Windows, Mac OS, Linux와 같은 OS 위를 이야기하죠!) 지원되는 라이브러리를 통해 구현할 수 있고, 이 라이브러리가 스케줄링 관리 및 스레드 생성, 삭제, 임계 영역 관리 등 관리 작업을 할 수 있게 해줘요. 한 프로세스가 갖는 메모리 영역을 같이 공유하며 사용하기 때문에 속도가 빠르지만, 여러 개의 쓰레드 중 한 개의 쓰레드라도 시스템으로부터 인터럽트가 들어오면 프로그램에 오류가 나기 때문에 잘 다뤄야 한다는 단점이 있어요!

Kernel Level Thread는 우리가 지금 만들고 있는 것과 같아요! 운영체제의 지원 가능한 쓰레드 기능으로 구현되고, 직접 태스크 관리 및 스케줄링 관리 등 관리를 해주어야 해요. 자칫 잘못하면 운영체제 실행이 잘못되어 블루스크린이 아닌 블랙스크린이 뜬다거나... 무한 부팅이 된다거나... 이렇게 쓰레드가 위험합니다 여러분 ㅜㅜ(제가 이것 저것 만지다가 경험해써여 헿헤헿헤헿) 위키백갓에서는 커널이 직접 관리해준다고 하는데 그 커널을 우리가 프로그래밍하고 있기 때문에 결국 우리가 관리해주는 것이랍니다!!


멀티 쓰레딩에서는 일대일, 다대일, 다대다 모델이 있다고 하는데 한 마디로 정리하자면 User Level Thread - Kernel Level Thread 매핑 기법에 따라 모델을 정해준거예요. 커널 영역 쓰레드를 중심으로 몇 개의 사용자 영역 쓰레드와 매핑되어 있는 지에 따라 공유영역을 어떻게 사용하는가, 자원 활용도와 속도는 어떤가를 나눈 모델이지요!

만약 10개의 사용자 영역 쓰레드가 1개의 커널 영역 쓰레드에 연결 되어 있다면 임계영역에 접근하는 관리를 잘 해주어야 하며 데드락이 걸리지 않도록 구현할 때 신경써야 하겠죠!?


이제 다시 책을 보면.. 메인 쓰레드에 대해 다뤄 주셨네요!! 메인 쓰레드를 쉽게 이해하기 위해 아까 등장했던 메모장을 다시 상기시켜보아요!


main

Main Thread(메인 쓰레드)는 멀티 쓰레딩 할 때 다대일 모델에서 가장 중심이 되는 쓰레드를 말하는데, 메인 쓰레드가 아닌 그 외 Sub Thread(서브 쓰레드)가 수행중일 때 메인 쓰레드가 종료되면 서브 쓰레드는 강제로 종료되므로 프로그램에 문제가 생기겠죠?! 그렇기 때문에 메인 쓰레드는 모든 서브 쓰레드가 수행을 정상적으로 마친 후 종료될 때까지 대기했다가 종료되어야 해요. 메모장 같은 경우에도 창 하나를 띄우기 위해 각 서브 쓰레드(제목 표시줄, 메뉴 표시줄, 각 탭 및 창)가 모두 구현 된 후 창 하나를 띄우는 메인 쓰레드가 종료되며 프로그램이 뚜둔! 하고 나오는 것이예요!!(나닛 뚜둔!?)



개미는 뚠뚠~(또 시작인 야미의 삼천포 스킬..헿) 이거 노래 중독성이써여!! 안물안궁이라구여? 넵... 쮸굴...


이렇게 중요한 메인 쓰레드의 역할을 빼먹을 뻔 했따닛!!! 역시 갓승훈 선생님의 책은 시스템 개발의 지표이자 꿈이자 목표인 것 같네여 데헷-☆

sub

Sub Thread는 Main Thread의 ID를 알아야 쓰레드 태스크를 종료한 후 메인 쓰레드에게 끝났다는 메시지를 보낼 수 있겠죠!? 또한 메인 쓰레드는 서브 쓰레드의 개수를 알아야 서브 쓰레드의 메시지 개수에 따라 메인 쓰레드를 종료할 수 있을테구요! Thread와 Process에 대해 ID값을 통하여 링크를 걸어 단순 연결리스트(LinkedList)로 연결하면 되지 않을까요?!


example

이렇게 이제 책의 구현부로 넘어가면 이번 챕터가 끝이나요!! 하지만 저는 Thread라는 것이 넘나 이론적인 것만 많아서 실습을 통한 습득이 더 좋다고 생각하는 1인입니당!! 이 전 포스팅에서 Mutex를 pthread 라이브러리를 통해 보여드렸는데, 이번엔 Thread를 간단한 실습을 통해 이해하도록 해보아여!!



약 15분간 코딩한 결과예여... 굳이 왜 계산기를 쓰레드와 함께 쓰는지 모르겠다!! 하시면 저는 할말이 없네영 ㅜㅠㅜ 그저 예제일 뿐인데... 예제가 참 이상하다 싶으시면... 제 두뇌 탓을 할게여 콩콩콩콩!


NUM 구조체는 쓰레드 생성과 함께 파라미터로 넘겨주기 때문에 공유변수가 아니지만, 이 또한 공유변수로 만들 수는 있어요! 정말 간단한 예제이기 때문에 getCnt 정수형 변수와 opcode 캐릭터 변수를 전역변수로써 공유변수로 사용했어요. getCnt 정수형 변수는 어떤 쓰레드가 몇 번 째로 수행하였는지를 나타내기 위해 사용했으며, opcode는 +, -, *, / 연산자를 확인하는 것으로 사용했지요!


먼저 main() 함수에서 Critical Section을 초기화시켜주고 mainThread() 함수를 Main Thread로 쓰레드 생성을 선언했어요.

그리고 mainThread() 함수를 보면... 예외처리랑 종료... 가 없네여 ㅜㅠ 이 쓸모없는 코딩실력이 이렇게 들통나네여 헿헤헿 입력받은 계산에 대하여 피연산자를 NUM 구조체의 v1과 v2 멤버변수에 넣고 연산자를 opcode에 넣어줘요! 그것을 기반으로 계산 함수(덧셈은 subThread_sum() 함수 / 뺄셈은 subThread_sub() 함수 / 곱셈은 subThread_mul() 함수 / 나눗셈은 subThread_div() 함수)를 Sub Thread로 쓰레드 생성을 선언했어요. 각 계산 함수는 실행 순서에 따라 순번을 출력하고, 실행할 때 먼저 임계영역을 잠궈 공유변수로 인한 데드락을 방지하고 opcode 확인 후 자신이 실행할 계산인지 검사하여 알맞게 출력한 후 리턴하도록 구현했어요!

정말 간단한 소스코드이지 않나여? 오류적인 부분이 너무나도 많아 창피하지만.. 그래도 예제잖아여!! 제대로 된 계산기도 아닐 뿐더러 쓰레드를 위한 예제이니까요!


이렇게 구현한 코드를 실행시키면 아래와 같이 나와요!



만약 크리티컬 섹션이 없다면 어떻게 될까요?! 이런거 막 궁금해지고 그렇지 않나여!? 그래서 해봤더니 이런 답이 나오네여!!

자신에게 알맞는 opcode를 찾은 함수는 이 후 연산을 수행해야하기 때문에 가장 나중에 출력되며, 그 외 opcode와 다른 함수는 else문을 출력 후 리턴하기 때문에 먼저 출력됩니다.

백문이 불여일견!! 직접 따라해보면서 조금씩 고쳐가며 쓰레드를 익혀보세여!! 그래야 이론이 좀 더 머릿속에 들어오실 거예여!!


이 정도의 쓰레드 예제로는 완벽히 감이 오지 않을테지만.. ㅜㅠ 위에서 보셨듯이 저의 코딩 실력이... 치부가... 이렇게 드러나버려서 늉늉...

쓰레드는 개발자가 아니어도 정말 중요한 개념이기 때문에 많은 실습을 통해 완벽히 숙지하시고 이해하시면 좋을 것 같아여!!(야미님부터 더 많은 실습을 하셔야 할 것 같은데여? 넵... 그렇네엽... 쭈굴...)


오늘 포스팅은 여기까지할게여!! 요즘 너무 성의없는 글을 쓰는 것 같아 너무 죄송합니당... 무슨 말을 해도 변명은 변명이니깐여 ㅜㅜ 더 열심히 하도록 할게여!! 다들 다음 포스팅에서 뵈어요!!


Check out the yummyhit’s website for more info on who am i. If you have questions, you can ask them on E-mail.

카테고리:

업데이트:

댓글남기기