[완료] RTOS에서 태스크 실행과 관련되어서 질문드리고 싶습니다.

nompaeng의 이미지

프로그램 하나를 분석하고 있는데.. 초기화를 해주는 부분입니다.
그런데 중간에 태스크를 생성해서 실행시키더군요.

그런데 그 아래 부분에 초기화 하는 내용이 들어가 있네요.
이럴 경우에 이 부분은 언제 실행이 되는건지요?

태스크를 생성해서 실행해 버리면 태스크의 우선순위를 보고서 해당 태스크로 뛰는거 아닌가요?

void Device_Init()
{
초기화....
어쩌구 저쩌구...

t_create(DR_task....); 태스크 생성
t_start(DR_task.....); 태스크 실행

[ 나머지 초기화들.... ]
}

[ ]로 둘러쌓인 저 나머지 초기화 부분은 언제 실행이 되는지요?

참고로.. Device_Init는 main 태스크에서 호출된 함수입니다.
그리고 DR_task는 장치로부터 데이터 수신을 담당하는 태스크 입니다.

혹시 Device_Init()함수를 호출한 태스크(main)의 우선순위가 저 함수안에서 만들어서 실행한
태스크(DR_task)보다 우선순위가 높으면 Device_Init()를 호출한 태스크(main)의 내용을 다
수행하고 새로 생성된 DR_task를 수행하게 되는건가요?

태스크 간의 처리가 어떻게 되는지 정확히 이해하지 못해서 잘 모르겠습니다.
답변 부탁드리겠습니다.
감사합니다.

espereto의 이미지

태스크 스케줄러가 어떻게 구현되었냐에따라 다르기는 합니다만.......
태스크가 작업을 처리하다 쉬는 시간이 생기게 되면 태스크 스케줄러에서 다른 태스크를 동작시키게 되고,
스케줄러에 따라서는 낮은 우선순위의 태스크라 하더라도 높은 우선순위만 실행시키는 것이 아니라 낮은 태스크도 실행되도록 배려하기도 합니다.
특히, 선점형 멀티태스킹의 경우 특정 태스크가 CPU를 독점하게 작성되어 있어도, 스케줄러가 강제로 다른 태스크에게 실행 기회를 줄 수도 있습니다. (특정 시간 단위로 쪼개서 각 태스크를 우선순위별로 번갈아가면서 실행하기도 하고......)
물론, 특정 태스크가 쉬지않고 동작한다면 선점형이 아닌 경우에는 해당 태스크가 CPU를 독점하는 경우가 생기기도 합니다. (이런 경우 태스크를 무조건 일만 하도록 하지 않고 적당히 sleep 함수를 호출하는 식으로 작성하기도 합니다.)
보통 태스크 스위칭이 일어나는 경우가, 세마포어 관련 함수를 호출하거나 Task Sleep 함수를 호출할 때, 또 특정한 시스템 함수를 호출할 때 스위칭이 됩니다.)

anfl의 이미지

몇가지 경우가 있을수 있는데.

1. preemption disable(scheduler가 locked 된 상황)인 경우
- DR_task는 main task가 preemption enable 할때까지 scheduling이 일어나지 않아 context switch가 일어나지 않습니다.

2. preemption enable이고 main task의 priority가 top priority일 경우
- 이 경우에도 문제가 되지 않겠죠. main task는 idle 상태로 빠질때 priority를 낮추거나 혹은 idle task를 생성하고 사라져버리면 문제 없습니다.

3. preemption enable이고 main task가 DR_task 보다 priority가 낮은경우
- 이 경우 context switch가 일어나지만 DR_task의 code 내부에 device로부터 전송되는 data가 없을경우 sleep 할것임으로 문제가 되지 않는다고 봐야할것 같네요. 경우에 따라서는 위험성을 내포하고 있기 때문에 이런식으로 초기화 하는건 좋은 방법이 아니겠죠.

대충 이 정도일것 같은데 보통 1번 방법이 정석에 가까운 방식임으로 1번 방식으로 구현되지 않았을까 쉽네요. 결론은 어떠한 방법으로 구현되었더라도 정상적으로 동작하려면 말씀하신 DR_task 이후의 초기화들이 이루어져야겠죠.


nompaeng의 이미지

사용하는 RTOS가 선점형이며, PREEMPTION을 허용하도록 만들어져 있습니다.
살펴보니 main task가 DR_task보다 우선순위가 낮은 3번의 경우입니다.

DR_task안에서 device전송정보를 기다리는 내용으로 작성되어있습니다. 즉 큐메시지를 받기위해
호출하는 함수가 있더라구요. 이때, 데이터가 없으면 sleep() 상태가 되어 main task로 돌아온 후
나머지 초기화 부분을 수행하게 되는 걸로 보입니다.

3번 방식으로 초기화하는게 좋지 않은 이유는 무엇인가요?

main task에서 호스트와의 통신을 위한 초기화 함수( Device_Init() )를 호출하고 이 함수안에서
DR_task (호스트와의 통신 task)를 수행한 후, 이후 초기화는 통신연결 상태를 기다리는 등의
순차적인 초기화를 합니다.

3번 방식이 좋지 않다면 위와 같은 구성의 프로그램을 어떠한 식으로 구성하는 것이 좋은지요?
귀찮으시더라도 한번만 더 도움 부탁드립니다. 감사합니다.

anfl의 이미지


제가 말한 1번의 preemption disable은 말씀하신 개념과는 틀립니다. 거의 모든 RTOS는 preemption 가능하게 설계가 되어있죠.

제가 말한 preemption disable은 sched_lock이 걸려있어서 scheduler가 호출될수 없는 상태를 말합니다. 보통 함수 호출에서 ScheduleLock() 혹은 PreemptionDisable() 이런류의 함수를 호출하고 들어간다면 preemption disable 상태라고 보시면 되고, 위 함수를 호출하지 않더라도, sched_lock 변수나 preemption_enable 변수와 같은 류의 변수에
어떠한 값을 설정하고 부팅한다면 역시나 preemption disable 상태라고 볼수 있을것 같네요.

자세한 상황은 해당 RTOS의 종류와 어떤식으로 구현되었는지 알때야 가능할것 같습니다.

어쨌던 3의 상태라면 말씀하신대로 "DR_task (호스트와의 통신 task)를 수행한 후, 이후 초기화는 통신연결 상태를 기다리는 등의 순차적인 초기화를 합니다." 이렇게 동작한다면
다음과 같은 문제가 있을수 있습니다.

1. device의 초기화가 완전히 끝나지 않은 상태에서 DR_task가 device에서 값을 읽어오려고해서 유효하지 않은 값으로 동작할수 있다.

2. 데이터를 전송하는 주체가 제대로 준비되지 않은 경우 데이터 전송이 완료될때까지 부팅시 기다릴수 있다.

3. device에서 어떠한 값을 읽어옴은 그 값을 이용하는 어떠한 application에게 처리하기 위함인데, 아직 부팅중이라서 application이 준비되지 않은 상태에서 값을 읽어와서 device 종류에 따라 시간차적 문제가 발생할수 있다.

이상과 같은 문제들이 내포될 수 있습니다. 이러한 문제들을 다 고려해서 Device_init()이 작성되었다 하더라도 보수적으로 프로그래밍 해야되는 RTOS 코드에 이렇게 가정이 들어가게 되면 나중에 RTOS 코드를 보수하던지 할때 현 상황의 문제가 고려되지 않을 경우 문제의 소지가 있기 때문에 좋지 않은 방법이라 할 수 있습니다.

해결 방법은 1번과 같이 바꾸던가 혹은 2번과 같이 바꾸던가 혹은 모든 device 초기화 완료후 DR_task를 생성하는게 좋을것 같네요.
단 이럴 경우 RTOS 소스를 가지고 있어야 할것이고, RTOS에 kernel에 대한 충분한 이해가 있어야 되겠죠. 그렇지 않다면 차라리 손대지 않는게 좋을것 같습니다.


nompaeng의 이미지

사용되어지는 OS는 pSOS입니다. 자료를 찾아헤매이다가 도큐먼트 폴더안에 숨어있던 pdf파일들을 찾았답니다.

DR_task가 생성되고 수행하는 동작을 살펴보니 q_vreceive(..)라는 큐메세지를 기다리게 되더라구요. 아무래도 이 시스템콜 함수 덕분에 blocked되고
그 다음 초기화 부분으로 넘어와서 수행이 되는거라 생각됩니다. 큐메세지를 보내는 q_vsend(...)함수가 인터럽트가 들어올 경우에 해당 서비스루틴이
실행되면서 동작시키는 특정 함수에서 동작을 하기에.. 인터럽트가 올때 수행되니까 초기화가 되겠구나 라고 생각했습니다.

그런데 여기서 한가지 의문점이 생겼습니다.

만약 저 부분을 수행하던 도중에(초기화중에) 인터럽트가 들어온다면, 초기화가 완료되지 않았는데 task가 먼저 실행하게 되는 일이 발생할 수도 있는건가요?
초기화 중에 인터럽트를 받지 않으면 되니까 초기화 중에는 인터럽트를 disable시키고 초기화 후에 enable시키는 형식으로 프로그램을 구성하면 되는지요?
원래 그렇게 되어있는데 제가 못찾고 있는건지.. ㅋ

os가 포팅된 펌웨어는 처음 다루어봐서 많이 부족합니다.
os없는 펌웨어는 좀 더 간단했었는데 이건 많이 어지럽네요.

답변 부탁드리겠습니다. 감사합니다.

anfl의 이미지

만약 저 부분을 수행하던 도중에(초기화중에) 인터럽트가 들어온다면, 초기화가 완료되지 않았는데 task가 먼저 실행하게 되는 일이 발생할 수도 있는건가요?

- 아마도 부팅 과정중에 interrupt disable 상태라 초기화가 완료되지 않은 상태에서 task는 수행되지 않을겁니다. 해당 코드에서의 interrupt 상태를 확인해보세요.

초기화 중에 인터럽트를 받지 않으면 되니까 초기화 중에는 인터럽트를 disable시키고 초기화 후에 enable시키는 형식으로 프로그램을 구성하면 되는지요?

- 네. 거의 모든 RTOS는 부팅시에 interrupt disable 상태로 부팅합니다.


nompaeng의 이미지

답변 정말 감사드립니다.
인터럽트를 어느시점에 enable시키는 지를 찾아보면 되겠네요.
많은 도움이 되었습니다. 감사드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.