[완료]pthread scheduling 관련 질문입니다.

caeshan의 이미지

일단 제가 원하는 것은 우선 순위가 50, 55인 쓰레드 두개를 라운드 로빈 스케줄링 정착하에 실행 시킵니다.
스레드가 하는 일은 그냥 간단하게 10000을 카운터하면 화면에 출력합니다.

제가 예상하기로는 두 쓰레드게 병렬적으로 수행하고 55의 우선 순위를 가지는 쓰레드가 50 보다 먼저 종료 되어야합니다. 그런데 이상하게 우선 순위가 50인 쓰레드 종료후 55인 쓰레드가 실행을 시작합니다. 즉 선점도 병렬수행도 안되는듯한데요...
(참고로 우순 순위가 50 인 것을 먼저 생성 하고 55을 생성합니다.)

[질문] 어떻게 하면 우선순위가 55 인것이 먼저 종료하게 하죠? (선점 , 병렬 수행)

------------------------------
실행 결과입니다.
maxium pri = 99
minium pri = 1
쓰레드 파라미터 , 상속, 우선순위 설정 완료
thread_routine 0 running at PR / 50
thread id = 0 / i = 0
thread id = 0 / i = 10000
thread id = 0 / i = 20000
thread id = 0 / i = 30000
thread id = 0 / i = 40000
thread id = 0 / i = 50000
thread id = 0 / i = 60000
thread id = 0 / i = 70000
thread id = 0 / i = 80000
thread id = 0 / i = 90000
thread id = 0 / i = 100000
thread id = 0 / i = 110000
thread id = 0 / i = 120000
thread id = 0 / i = 130000
thread id = 0 / i = 140000
thread id = 0 / i = 150000
thread id = 0 / i = 160000
thread id = 0 / i = 170000
thread id = 0 / i = 180000
thread id = 0 / i = 190000
thread_routine 1 running at PR / 55
thread id = 1 / i = 0
thread id = 1 / i = 10000
thread id = 1 / i = 20000
thread id = 1 / i = 30000
thread id = 1 / i = 40000
thread id = 1 / i = 50000
thread id = 1 / i = 60000
thread id = 1 / i = 70000
thread id = 1 / i = 80000
thread id = 1 / i = 90000
thread id = 1 / i = 100000
thread id = 1 / i = 110000
thread id = 1 / i = 120000
thread id = 1 / i = 130000
thread id = 1 / i = 140000
thread id = 1 / i = 150000
thread id = 1 / i = 160000
thread id = 1 / i = 170000
thread id = 1 / i = 180000
thread id = 1 / i = 190000
메인 종료

-----------------------------------
소스 코드입니다.

/* 컴파일 : gcc -o testpri testprie.c -lpthread
* 실행 명령어 : sodo ./testpri2 (ubuntu 환경 )
* 참고 페이지 : http://man.kldp.org/wiki/ManPage/pthread_setschedparam.3
* 참고 : pthread_setschedparam은 수퍼 유저 권한을 가지 사용자가 실행하여야한다.
*
*/
#include
#include
#include

#define THREADS 2
/*각 스레드를 나타내는 구조체 */
typedef struct thread_tag{
int index;
pthread_t id;
pthread_attr_t thread_attr;
} thread_t;
thread_t threads[THREADS];
int rr_min_priority,rr_max_priority;

/*쓰레드 실행 루틴 */
void *thread_routine (void * arg)
{

thread_t *self = (thread_t *) arg;
int my_policy; //현재 쓰레드의 스케줄링 정책 확인용
struct sched_param my_param; //현재 쓰레드의 파라미터값 확인용
int status;
int i;


//스케줄링 정책 파마리터 확인
status = pthread_getschedparam(self->id, &my_policy, &my_param);

if (status!= 0)
printf("error at geting sched param\n");
// 읽어온 쓰레드 정보 출력
printf("thread_routine %d running at %s / %d\n",
self->index,
(my_policy == SCHED_FIFO ? "FIFO"
: (my_policy == SCHED_RR ? "PR"
: (my_policy == SCHED_OTHER ? "OTHRER"
: "unknown"))),
my_param.sched_priority);

//작업 수행
for(i=0; i<10000*20;i++)
{ if ( i % 10000 ==0 )printf ("thread id = %d / i = %d\n",self->index, i);

}
}


int main( int argc, char *arg[])
{
struct sched_param thread_param;
int count, status;

int total_roof;
total_roof=0;

// 쓰레드 스케줄링 지원 여부 체크
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined (sun)

//우선순위 최고값 최소값 확인
rr_max_priority = sched_get_priority_max(SCHED_RR);
printf("maxium pri = %d\n" , rr_max_priority);
rr_min_priority = sched_get_priority_min(SCHED_RR);
printf("minium pri = %d\n" , rr_min_priority);

for (count = 0; count < THREADS; count++)
{

//스케줄링 정책 셋팅
status = pthread_attr_setschedpolicy( &threads[count].thread_attr, SCHED_RR);
//스케줄링 우선 순위 설정 ( 우선 순위= (최고 +최소)/2 + count*5 )
thread_param.__sched_priority= ( rr_min_priority + rr_max_priority)/2 + count*5;
status = pthread_attr_setschedparam( &threads[count].thread_attr , &thread_param);
//스케줄링 상속 설정
status = pthread_attr_setinheritsched(&threads[count].thread_attr, PTHREAD_EXPLICIT_SCHED);


}
printf ("쓰레드 파라미터 , 상속, 우선순위 설정 완료\n");
#else
printf(" 쓰레드 스케줄링이 지원되지 않습니다\n");
#endif


//쓰레드 생성 및 실행
for(count = 0; count < THREADS ; count++)
{
threads[count].index = count;
status = pthread_create (
&threads[count].id, &threads[count].thread_attr,
thread_routine, (void *)&threads[count]);
if (status!= 0)
printf("error at creating thread/n");
}
//쓰레드 종료대기
for(count = 0; count < THREADS; count++)
{
status = pthread_join ( threads[count].id, NULL);
if (status!= 0)
printf("error at joying thread/n");
}
printf ("메인 종료\n");
return 0;


}

winner의 이미지

Thread 1이 실행되기도 전에 thread 0가 끝나는 것 아닌가요?

caeshan의 이미지

위에 예제는 결과 한 화면에 출려할려고 시간 적게 준것이고요 시간을 5분으로 줘도 thread0의 실행이 끝나야 thread1이 시작된답니다.
위에 예제 그냥 testprie.c 에 저장한후 컴파일하면 실행되는데 확인해 보셔도되고요 . 아참 이거 루트 권한 가지고 실행하셔야합니다.

caeshan의 이미지

위에 소스에서 thread rutine을 while로 감싸고 쓰레드 50 에는 usleep(1000) 쓰레드 70에는 usleep(500)을 주었습니다.

-------------------------수정 코드------------------------------------
while(1){
for(i=0; i<10000*10;i++)
{ if ( i % 10000 ==0 )printf ("thread id = %d / i = %d\n",self->index, i);

}
if( self->index == 0 )usleep(1000);
else usleep(500);


}
-------------------------------------------------------------------------
아래 실행 결과를 보시면 처음에는 쓰레드 50이 먼저 실행되지면 일정 시간이 지나면 쓰레드 70에 50으로부터 자원을 선점 함을 볼수있습니다.

-----------------실행 결과-------------------------------------------------
mmaxium pri = 99
minium pri = 1
쓰레드 파라미터 , 상속, 우선순위 설정 완료
thread_routine 0 running at PR / 50
thread id = 0 / i = 0
thread id = 0 / i = 10000
thread id = 0 / i = 20000
thread id = 0 / i = 30000
thread id = 0 / i = 40000
thread id = 0 / i = 50000
thread id = 0 / i = 60000
thread id = 0 / i = 70000
thread id = 0 / i = 80000
thread id = 0 / i = 90000
thread id = 0 / i = 0
thread id = 0 / i = 10000
thread id = 0 / i = 20000
thread id = 0 / i = 30000
thread id = 0 / i = 40000
thread id = 0 / i = 50000
thread id = 0 / i = 60000
thread id = 0 / i = 70000
thread id = 0 / i = 80000
thread id = 0 / i = 90000
thread_routine 1 running at PR / 70
thread id = 1 / i = 0
thread id = 1 / i = 10000
thread id = 1 / i = 20000
thread id = 1 / i = 30000
thread id = 1 / i = 40000
thread id = 1 / i = 50000
thread id = 1 / i = 60000
thread id = 1 / i = 70000
thread id = 1 / i = 80000
thread id = 1 / i = 90000
thread id = 0 / i = 0
thread id = 0 / i = 10000
thread id = 0 / i = 20000
thread id = 1 / i = 0
thread id = 1 / i = 10000
thread id = 1 / i = 20000
thread id = 1 / i = 30000
thread id = 1 / i = 40000
thread id = 1 / i = 50000
thread id = 1 / i = 60000
thread id = 1 / i = 70000
thread id = 1 / i = 80000
thread id = 1 / i = 90000
thread id = 0 / i = 30000
thread id = 0 / i = 40000
thread id = 0 / i = 50000
thread id = 1 / i = 0
thread id = 1 / i = 10000
thread id = 1 / i = 20000
thread id = 1 / i = 30000
thread id = 1 / i = 40000
thread id = 1 / i = 50000
thread id = 1 / i = 60000
thread id = 1 / i = 70000
thread id = 1 / i = 80000
thread id = 1 / i = 90000
thread id = 0 / i = 60000
thread id = 0 / i = 70000
thread id = 1 / i = 0
thread id = 1 / i = 10000
thread id = 1 / i = 20000
thread id = 1 / i = 30000
thread id = 1 / i = 40000
thread id = 1 / i = 50000
thread id = 1 / i = 60000
thread id = 1 / i = 70000
thread id = 1 / i = 80000
thread id = 1 / i = 90000
thread id = 0 / i = 80000
thread id = 0 / i = 90000
thread id = 1 / i = 0
thread id = 1 / i = 10000
thread id = 1 / i = 20000
thread id = 1 / i = 30000
thread id = 1 / i = 40000
thread id = 1 / i = 50000
thread id = 1 / i = 60000
thread id = 1 / i = 70000
thread id = 1 / i = 80000
thread id = 1 / i = 90000
thread id = 0 / i = 0
thread id = 0 / i = 10000
thread id = 0 / i = 20000
thread id = 1 / i = 0
thread id = 1 / i = 10000
thread id = 1 / i = 20000
thread id = 1 / i = 30000
thread id = 1 / i = 40000
thread id = 1 / i = 50000
thread id = 1 / i = 60000
thread id = 1 / i = 70000
thread id = 1 / i = 80000
thread id = 1 / i = 90000
thread id = 0 / i = 30000
thread id = 0 / i = 40000
thread id = 0 / i = 50000
thread id = 1 / i = 0
thread id = 1 / i = 10000
thread id = 1 / i = 20000

-----------------------------------------------------------수정 코드 전체---------------------------------------------------

/* date : 08 07 06
* 컴파일 : gcc -o testpri testprie.c -lpthread
* 실행 명령어 : sodo ./testpri2 (ubuntu )
* 참고 페이지 : http://man.kldp.org/wiki/ManPage/pthread_setschedparam.3
* 참고 : pthread_setschedparam은 수퍼 유저 권한을 가지 사용자가 실행하여야한다.
* 문제 : 쓰레드간 선점이 일어 나지 않는거같다.
*/
#include
#include
#include

#define THREADS 2
/*각 스레드를 나타내는 구조체 */
typedef struct thread_tag{
int index;
pthread_t id;
pthread_attr_t thread_attr;
} thread_t;
thread_t threads[THREADS];
int rr_min_priority,rr_max_priority;

/*쓰레드 실행 루틴 */
void *thread_routine (void * arg)
{

thread_t *self = (thread_t *) arg;
int my_policy; //현재 쓰레드의 스케줄링 정책 확인용
struct sched_param my_param; //현재 쓰레드의 파라미터값 확인용
int status;
int i=0;


//스케줄링 정책 파마리터 확인
status = pthread_getschedparam(self->id, &my_policy, &my_param);

if (status!= 0)
printf("error at geting sched param\n");
// 읽어온 쓰레드 정보 출력
printf("thread_routine %d running at %s / %d\n",
self->index,
(my_policy == SCHED_FIFO ? "FIFO"
: (my_policy == SCHED_RR ? "PR"
: (my_policy == SCHED_OTHER ? "OTHRER"
: "unknown"))),
my_param.sched_priority);

//작업 수행
while(1){
for(i=0; i<10000*10;i++)
{ if ( i % 10000 ==0 )printf ("thread id = %d / i = %d\n",self->index, i);

}
if( self->index == 0 )usleep(1000);
else usleep(500);

//printf ("thread id = %d / i = %d\n",self->index, i);
//sleep(2);
}
}


int main( int argc, char *arg[])
{
struct sched_param thread_param;
int count, status;

int total_roof;
total_roof=0;

// 쓰레드 스케줄링 지원 여부 체크
#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && !defined (sun)

//우선순위 최고값 최소값 확인
rr_max_priority = sched_get_priority_max(SCHED_RR);
printf("maxium pri = %d\n" , rr_max_priority);
rr_min_priority = sched_get_priority_min(SCHED_RR);
printf("minium pri = %d\n" , rr_min_priority);

for (count = 0; count < THREADS; count++)
{

//스케줄링 정책 셋팅
status = pthread_attr_setschedpolicy( &threads[count].thread_attr, SCHED_RR);
//스케줄링 우선 순위 설정 ( 우선 순위= (최고 +최소)/2 + count*5 )
thread_param.__sched_priority= ( rr_min_priority + rr_max_priority)/2 + count*20;
status = pthread_attr_setschedparam( &threads[count].thread_attr , &thread_param);
//스케줄링 상속 설정
status = pthread_attr_setinheritsched(&threads[count].thread_attr, PTHREAD_EXPLICIT_SCHED);


}
printf ("쓰레드 파라미터 , 상속, 우선순위 설정 완료\n");
#else
printf(" 쓰레드 스케줄링이 지원되지 않습니다\n");
#endif


//쓰레드 생성 및 실행
for(count = 0; count < THREADS ; count++)
{
threads[count].index = count;
status = pthread_create (
&threads[count].id, &threads[count].thread_attr,
thread_routine, (void *)&threads[count]);
if (status!= 0)
printf("error at creating thread/n");
}
//쓰레드 종료대기
for(count = 0; count < THREADS; count++)
{
status = pthread_join ( threads[count].id, NULL);
if (status!= 0)
printf("error at joying thread/n");
}
printf ("메인 종료\n");
return 0;


}

kerino의 이미지

원인은 policy가 RR이기도 하지만, RT프로세스로 수행이 되고 있기 때문입니다.

SCHED_RR : RT 프로세스
SCHED_FIFO : RT 프로세스
SCHED_OTHER(NORMAL) : 일반 프로세스
SCHED_BATCH : 일반 프로세스

처음 예제에서 '우선순위:50'이 수행되는 구간에서는 '우선순위:55' 프로세스는 생성조차 되지 않습니다.
RT 프로세스는 일반 프로세스보다 무조건 우선순위가 높으며 따라서 일반 프로세스에 의해서는 선점 되지 않습니다.
따라서, 우선순위:50 프로세스는 수행됨과 동시에 main 프로세스의 수행을 막아 우선순위:55 프로세스의 생성을 막게 됩니다.
(이것은 몇 시간이 되었건 '우선순위:50' 프로세스가 수행되는 동안에는 그렇습니다.)

참고로, RR이나 FIFO 은 동일한 우선순위를 갖는 프로세스에서 적용 되는 규칙입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.