저번 토요일에 논쟁거리 였던 스핀락에 대한 제 생각을 정리해보겠습니다.(틀리다면 지적해주세요)
먼저 스핀락을 말하기 전에 커널에서 동기화가 필요한 부분에 대해서 설명 할께요
인터럽트 동기화를 위한 스핀락도 사용 커널에서의 동기화랑 비슷하다고 생각합니다.
따라서 커널 동기화 부분만 예를 들겠습니다.
1. UP에서 커널 동기화 문제
실제로 유저단에서 프로그램이 돌고 있다가 시스템 콜로 커널로 진입합니다.
(질문1 :커널에 진입하기전에 유저단에서 C라는 자원을 가지고 작업하고 있다가 커널로 진입하여 똑같은 C라는 자원을 접근할 경우가 있나요??(인터럽트 또는 시스템콜 으로) 제 생각으로는 message massing 방법에서 이런 경우가 있을 수도 있다고 (억지스러운)생각은 하지만 이럴 겨우는 없다고 생각이 듭니다.)
1> 가능성 1
이때, 커널에서 동기화 문제는 커널에서의 A라는 자원을 가지고 작업을 하고 있는데 B라는 인터럽트가 들어와서
현재 커널code를 선점하는 경우 입니다. 이때 B 인터럽트 핸들러(top half)에서 A라는 자원을 접근 하면 동기화 문제가 발생합니다.
따라서 커널에서 A라는 자원을 가지고 작업을 하기 전에 인터럽트 를 disable해야 합니다.
2> 가능성 2
그리고 만약 커널이 선점형이라면 커널에서 D라는 자원을 작업하다가 선점 된 경우
다른 프로세스가 똑같은 방식으로 시스템 콜로 커널로 진입하여 D라는 자원에 접근하는 경우 동기화 문제가 발생합니다.
(만약 커널선점형이 아니라면 생각할 필요도 없겠죠)
따라서 커널에서 D라는 자원을 가지고 작업을 하기 전에 커널을 preempt disable 해야합니다.
UP에서는 결론적으로 커널에서 공유 자원을 사용하기 전에는 인터럽트를 disable 하고 preempt disable 해야합니다.
(리눅스에서 thread_info 구조체에서 (스핀락 같은)락을 할때마다 preemptCount??? 변수가 1씩 증가한다고 합니다. 그래서 그 변수가 0 이 아니면 선점이 불가능하다고 하더군요)
커널은 처음엔 UP만을 고려하여 작성 되었기 때문에 만약 SMP환경으로 넘어 간다면 문제점이 발생합니다.
2. SMP에서 커널 동기화 문제
A와 B라는 CPU가 있다고 가정한다면,
먼제 A라는 CPU에서 유저단에서 프로그램이 돌고 있다가 시스템 콜로 커널로 진입합니다.
그리고 커널에서 공유 자원 E를 접근 하기 전에 위에서 언급한 모든 가능성을 없애기 위해서
preempt disable 하고 인터럽트도 disable 합니다.
하지만 여기서 문제가 발생하는데요, 바로 다른 B라는 CPU에서 공유 자원 E를 접근 할 수 있다는 겁니다.
따라서 커널 개발자들이 생각해 낸 것이 바로 스핀락의 개념입니다.
스핀락을 걸고 커널에서 작업을 한다면 B라는 CPU에서 공유 자원 E를 접근 할 수 없습니다. (A에서 스핀락을 풀 때 까지)
A라는 cpu 커널에서는 락이 걸린 상태에서 preempt 될 수 없으므로 스핀락은 언젠가 반드시 풀고 선점되게 됩니다.
B 라는 cpu에서는 계속적으로 A에서 스핀락 풀때까지 pulling 하고 있다가 풀리면 E라는 공유 자원에 접근하게 됩니다.
따라서 정리하면 스핀락이라는 개념은 결국 CPU끼리 빠른 동기화 처리를 하기 위해 생겨난 UP에서 없었던 개념입니다.
(아 SMP에서 두 cpu간 동기화가 꼭 스핀락만 있는 것은 아닌 것 같습니다, 다만 빠른 처리를 위해서 스핀락이 생긴 것 같아요
SMP 환경의 이점을 활용하기 위한 동기화 방법이 스핀락인 것 같습니다. :D)
(질문 2 : 스핀락은 유저 단에서 사용될 이유도 없을 것 같은데요?)
(질문 3 : 세마포어 커널에서 사용 가능 하겠죠? )
댓글 19
-
홍문화
2011.04.25 16:11
-
이종인
2011.04.26 00:44
헷갈리네요 ㅋㅋ 세마포어가 시스템 콜이라면 커널 영역에서 못 사용 할 것 같아서요 ㅠ.. 아리송 하네요;
-
paul1206
2011.04.25 22:21
spinlock은 락을 잡고 있는 동안에는 인터럽트도 접근 불가능 하므로
블락킹되거나 wait큐등이 포함된 코드에는 사용되지 않습니다.
중요하고 빠르게 처리 해야하는 부분에 쓰일 것입니다.
spinlock은 함수일 뿐이죠.. 해당하는 쓰임새가 있으니 그에 맞게 쓰였을 것입니다.
나중에 코드를 볼때 spinlock이 나오면 그안에 있는 코드가 왜 spinlock을 썻는지 고민해야겠지요.
동시성에 쓰이는 잠금이나 상호배제 방법이 많으니 개념을 잡는데 중점을 두는게 좋을듯 합니다.
그리고 동시성은 자원공유에 대한 문제니 비선점up를 제외한 선점형 up, smp, 비선점 smp등에는 spinlock이 쓰이겠지요.
그리고 자원공유에대한 것들이니 user단에서 사용하는것은 위험이 크지 않을까합니다.
-
paul1206
2011.04.26 10:53
음~ spin_lock()을 말하는게 아니고 spinlock의 매커니즘을 말씀드린거구요.
원래 spinlock은 smp때문에 생겼지만 커널 2.6은 선점이 되기때문에 up에서도 spinlock이 쓰이죠.
-
이종인
2011.04.26 00:40
책 140페이지를 보시면 spinlock 함수 목록이 나오는데요, 모든 스핀락 함수가 인터럽트를 막는 것이 아니고
spink_lock_irq()함수나 spink_lock_irqsave()함수 만이 로컬 인터럽트를 막는 것 같습니다.
UP 자체는 spinklock의 개념이 없지 않나요? 선전혐 UP에서 spinlock이 쓰일 수 있다고 하신 것 같은데 ;;;;;;
-
홍문화
2011.04.25 23:40
(질문1 :커널에 진입하기전에 유저단에서 C라는 자원을 가지고 작업하고 있다가 커널로 진입하여 똑같은 C라는 자원을 접근할 경우가 있나요??(인터럽트 또는 시스템콜 으로) 제 생각으로는 message massing 방법에서 이런 경우가 있을 수도 있다고 (억지스러운)생각은 하지만 이럴 겨우는 없다고 생각이 듭니다.)
=> 질문이 정확하게 이해가 안되어 두가지로 분류 해봅니다.
1. 유저 영역에서 사용하던 자원을 커널 영역에서 연속해서 사용 할수 있냐?
2. 유저영역과 커널영역 간에 자원 동기화 문제가 발생 할 수 있냐?
1. 의 경우라면 아주 많이 사용하고 있습니다. write() 함수를 예로 들면 call by value든 call by reference든 유저 영역의
메모리가 커널 영역으로 넘어 갑니다. 커널에서는 copy_from_user()함수를 통해 유저 영역의 메모리를 가져옵니다.
2. 의 경우라면 아주 특수한 경우가 아니고서는 동기화 문제는 발생하지 않을거라 생각합니다. 기본적으로 커널 영역과
유저 영역간의 동기화 문제는 발생 해서 안된다고 생각합니다. 가장 기본적인 시스템 자원인 메모리를 예로 들어
보겠습니다. 이번주에 시작 될 메모리 파트를 공부하게 된다면 확실히 이해 되겠지만 시스템 콜을 제외하고는
유저 영역과 커널 영역의 메모리는 공유 될 수 없다고 합니다. 적절한 예가 될지는 모르겠지만 시스템 콜을 통해
커널영역으로 call by reference로 넘겨준 메모리를 커널 영역에서 사용하는 동안 유저 영역에서 건드리면
동기화가 깨지겠죠. 반대의 예를 들자면 mmap() 으로 특정 디바이스의 메모리를 유저영역으로 맵핑해서 사용하는
동안 시스템 콜을 통해 이 디바이스의 메모리를 건드리면 동기화가 깨지겠죠.
(질문 2 : 스핀락은 유저 단에서 사용될 이유도 없을 것 같은데요?)
=> 역시 가장 흔히 접하는 메모리를 예로 들어 유저영역에서 동기화가 필요한 경우 뮤택스나 세마포어 같은
시스템 콜을 사용합니다. 즉, 커널 영역으로 넘어갈 것이고 이 때 SMP 시스템 이라면 뮤택스, 세마포어 본연의 기능과
함께 스핀락이 같이 동작 할거라고 봅니다. UP 시스템이라면 뮤택스, 세마포어 본연의 기능만 할테구요. 즉,
유저영역에서 스핀락을 직접 사용할 필요가 전혀 없다고 봐야겠습니다. 만일 유저영역에서 스핀락 처리까지
프로그래머가 직접 해줘야 한다면 개발자는 미쳐버리거나 미쳐버리기 전에 이바닥을 뜨는게 상책이겠죠. ㅋㅋ
-
이종인
2011.04.26 00:42
아 질문이 애매했군요 ;;;ㅋ 저는 유저영역과 커널영역간에 자원 동기화 문제가 발생할 수 있냐 라는 질문이였습니다:D
-
오시리스
2011.04.27 16:31
UP가 뭐지요? x86초급인데, 궁금해서 지나다가 질문납깁니다 ㅎㅎ
스핀락이 SMP를 위해서 만들어졌다는고 말하셨는데... 제가 알고 있던거와는 달라서 질문드립니다.
일반적으로 빠른 처리가 필요하며, 문맥교환이 일어나서는 안되는 인터럽트 문맥이나 프로세스 문맥에서
사용되어 지는걸로 알고 있고, 관련 spinlock 함수중 irq변종은 call하는 부분은 같으나 멀티 프로세서일 경우,
다른 프로세서가 임계영역에 접근하는 것을 막아두는 부분을 컴파일러 단에서 포함한다고 알고 있는데, 그렇게
되는 경우 2번에서 SMP를 위해서 만들어진 개념이라고 하면 제가 알던 거와 다른것 같아서, 물어봅니다.^^;
-
오시리스
2011.04.27 22:55
(ARM중급이 아니라서, 몇번을 쓸까 말까 했지만..)
닭이 먼저냐 달걀이 먼저냐 했을때, 닭이 먼저다. 어? 나는 달걀이 먼저인줄 알았는데... 왜 닭이 먼저라고 그런거지?
하지만, 이것은 무엇을 먼저라고 정하는게 아니라, "내가 모르는것"을 알고자 함이란걸 알아주셨으면 하네요.
(딴지를 거는것도... 토론에 지장을 주기 위해 중요한 문제가 되고 싶은 마음도 없습니다.)
-
paul1206
2011.04.28 13:02
워~ 그렇군요.
책을 열심히 봐야겠네요ㅋ
-
홍문화
2011.04.28 09:50
커널 컴파일 시 SMP 옵션이 있습니다. 이 옵션에 따라 spinlock의 운명?이
좌우 되겠죠. ㅋㅋ
교재에 나오는 내용이구요. P.126에 나오네요.
-
paul1206
2011.04.28 09:22
궁금한게 있는데요.
up에서 이미 짜여진 spinlock코드는 어떻게 되나요??
up와 smp에 따라 코드가 다른가요?
-
홍문화
2011.04.28 00:32
프로세스문맥&인터럽트 문맥이 존재하며, 단일 프로세서, 커널 선점일 경우에는
커널선점을 비활성화 하고, 인터럽트를 비활성화한다 라고 되어 있습니다.
=> 프로세스문맥만 있을 경우에는 선점만 금지 하면 되구요. 인터럽트 문맥이 더해지면 선점도 금지하고 인터럽트도 금지해야
한다는 뜻으로 파악 됩니다.
거기에 쓰여지는 것은 spin_lock_irqsave/spin_unlock_irqrestore로 되어 있으며
내부적으로 preempt_disable과 preempt_enable호출이 되어 지구요.
=> 이부분은 좀 이상한데 spin_lock_irqsave/spin_unlock_irqrestore 이 아니라 local_irq_save/local_irq_restore로 바뀌어야 되지 않나 생각합니다. 이 두 함수는
찾아보시면 아시겠지만 선점 금지와 인터럽트 금지를 한꺼번에 하고 해제도 한꺼번에
해주는 함수 입니다. 정확히 말하면 인터럽트가 금지되면 선점은 같이 금지 됩니다.spin_lock_irqsave/spin_unlock_irqrestore 이 두함수는 여기에 스핀락, 스핀언락이
기능이 추가된 놈인데 프로세서가 하나라면 컴파일 시 스핀락, 스핀언락 기능이 빠지게 됩니다.
즉, 단일 프로세서에서는 local_irq_save/local_irq_restore와 동일하다고 보시면 됩니다. -
오시리스
2011.04.27 23:54
홍문화님 글과 백창우님 답변보며 납득을 하다가, 아리송한게 있어서 책을 봤는데..
음, 혼란스러워지네요 ㅎㅎ;;
일단 제가 보고 있는 책을 참고(코드로 읽는 리눅스 드라이버)하자면,
프로세스문맥&인터럽트 문맥이 존재하며, 단일 프로세서, 커널 선점일 경우에는
커널선점을 비활성화 하고, 인터럽트를 비활성화한다 라고 되어 있습니다.
거기에 쓰여지는 것은 spin_lock_irqsave/spin_unlock_irqrestore로 되어 있으며
내부적으로 preempt_disable과 preempt_enable호출이 되어 지구요.
인터럽트 처리기 내부라면 모르겠지만, 프로세스 문맥에서 스핀락이 쓰여진다면.. 선점과도
관계있지 않나 해서 댓글 달아봅니다.
-
홍문화
2011.04.27 23:09
spinlock은 선점 여부와는 상관이 없다고 생각합니다. 선점이란 곧 유사 동시성을 말하는 것이니까요.
그럼 왜 2.4에 spinlock 코드가 있냐? SMP에서 유저모드가 진정한 동시성을 가지기 때문이라고 봅니다.
-
paul1206
2011.04.27 22:24
닭이 먼저냐 달걀이 먼저냐 얘기같은데요...
2.4는 비선점 커널인데 왜 spinlock 코드가 있는지 생각해보시면 될것 같군요...
뭐 smp를 위해서건 뭘 위해서건 중요한문제는 아닌듯하군요..
-
오시리스
2011.04.27 22:17
SMP가 아닌, 단일 프로세서 + 선점형 커널의 경우에도, 프로세스 A와 프로세스 B도 스핀락을 이용해 동기화를 할 수 있지 않나요? 멀티 프로세스 환경에서는 spin_lock_irq 관련 함수가 다른 cpu의 임계영역 접근을 막는(자세한 메커니즘은 모르겠습니다)역할까지 한다고했는데...
제가 궁금했던 부분은 이 부분이었습니다. 단일 코어& 선점형 커널에서 부터 스핀락을 이용해, 동기화를 사용했다고 들었는데, 왜 SMP를 위해서 만들어진 개념이라고 하셨을까.. 라는 것이었습니다. ^^;;
-
이종인
2011.04.27 19:22
빠른 처리가 필요하다는 것과 문맥교환이 일어나서는 안되는 영역, 즉 공유자원 접근시 스핀락이 필요하다는 것 모두 맞는 말입니다.
SMP 예를 들어 볼께요..
SMP에서 cpu가(정확히는 core가) A, B 이렇게 2개 있다고 가정한다면,
A라는 cpu에서 문맥교환이 일어나지 않더라도(심지어 인터럽트 전부를 막아버린다 해도) 다른 1개 B라는 cpu에서 A가 실행 하고 있는 영역에 접근 할 수 있는 가능성이 있습니다.
이런 동기화 문제를 해결하기 위해서 A라는 cpu에서 작업을 수행전에 spinlock류의 함수를 쓰면, B라는 cpu는 (A가 락걸고 실행하고 있는 영역) A가 수행중인 영역을 접근할려고 하면 busy waiting 방식(하드웨어 종속적이라고 하더군요;)으로 A가 unSpinkLock() 류의 함수를 수행 전까지 대기 합니다.
A가 unSpinkLock()을 하는 순간 B라는 CPU가 그 동기화된 영역을 접근 할 수 있겠죠...
아, 가만 생각해보니까 ;; 스핀락을 쓰지 않아도 A라는 cpu와 B라는 cpu는 동기화 할 수도 있을 것 같습니다. 다만 B라는 cpu는 busy_waiting 방식으로 기다리는 것이 아니라 휴면(세마포어처럼) 하는 식이겠죠??; SMP에서 스핀락의 이점은 말씀 하신데로 빠른 접근 인것 같습니다. :D
SMP에서 동기화를 위해서 만들어진 개념이라기 보다는 SMP에서 빠른 동기화 처리를 위한 개념이라고 정정해야 될 것 같습니다...;;
-
홍문화
2011.04.27 17:08
저희가 사용하는 교재에서 uniprocessor를 UP로 표기하고 있어서 그대로 사용하고 있습니다. ㅋ
문맥교환이 일어나서는 안되는 인터럽트 문맥이나 프로세스 문맥은 어떤 문맥을 말하는 것일까요?
이 문맥의 의미를 이해하시면 반 이상은 이해 하실듯 하는데... ^^
.
(질문 3 : 세마포어 커널에서 사용 가능 하겠죠? )
=> 이번에 공부한 내용이 커널에서 세마포어 사용하는 방법 이었습니다. ㅋ ^^;