스케줄러 관련 시스템 콜

EEEFFEE·2023년 12월 4일

System Programming

목록 보기
19/19

23.12.04 최초 작성

1. 스케줄러 정책과 우선순위

  • sched_setscheduler : 스케줄러의 우선 순위를 변경하는 시스템 콜

#include <sched.h>

int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);

struct sched_param{
	int sched_priority;
}

///
pid : 스케줄러 우선 순위 변경할 프로세스 지정 (0 : 호출 프로세스)
policy : 스케줄러에 설정할 스케줄링 방법
param : policy의 매개변수 값

Return 
0 : Success, -1 : Fail

policy에 지정할 수 있는 값

SCHED_FIFOSCHED_RRSCHED_OTHERSCHED_BATCHSCHED_IDLE
First in First outRound Robin표준 라운드 로빈BATCH아주 낮은 우선순위의
백그라운드 작업 실행
  • sched_getscheduler(), sched_getparam() : 스케줄러 정책과 그 매개변수를 확인하는 함수

#include <sched.h>

int sched_getscheduler(pid_t pid);

///
pid : 스케줄링 정책 확인 할 프로세스

Return : 스케줄링 정책
-1 : Fail

int sched_getparam(pid_t pid, struct sched_param *param);

///
pid : 스케줄링 정책의 인자를 확인 할 프로세스
param : 스케줄링 정책의 인자를 저장 할 프로세스

Return 
0 : Success, -1 : Fail

2. CPU 친화도 설정

  • sched_setaffinity(), sched_getaffinity() : cpu 친화도 학인하는 함수

#define _GNU_SOURCE
#include <sched.h>

int sched_setaffinity(pid_t pid, size_t len, cpu_set_t *set);
int sched_getaffinity(pid_t pid, size_t len, cpu_set_t *set);
///
pid : 설정 / 확인 할 프로세스
len : set이 가리키는 데이터의 길이 (바이트)
set : 친화성 마스크를 표현하는 자료구조로 설정할 친화도 / 친화도를 저장할 공간

Return

0 : Success, -1 : Fail

  • 마스크를 설정하는 함수

void CPU_ZERO(cpu_set_t *set);								//마스크 초기화
void CPU_SET(int cpu, cpu_set_t *set);						//마스크에 cpu 설정
void CPU_CLR(int cpu, cpu_set_t *set);						//마스크에 cpu 해제
void CPU_ISSET(int cpu, cpu_set_t *set);					//마스크에 cpu 있는지 확인

Return

1 : Success, 0 : Fail

ex) 예제


#include <sys/types.h>
#include <sys/stat.h>
#include <sys/user.h>
#include <stdio.h>
#include <stdlib.h>

/* 스레드 상태 */
#define FREE        0x0 // 초기 상태
#define RUNNING     0x1 // 동작
#define RUNNABLE    0x2 // 대기 상태

#define STACK_SIZE  8192
#define MAX_THREAD  4

typedef struct task_struct task_struct_t, *task_struct_p;
typedef struct mutex mutex_t, *mutex_p;

struct task_struct {
  int        sp;                /* 스택 포인터 */
  char stack[STACK_SIZE];       /* 현재 스레드의 스택 */
  int        state;             /* FREE, RUNNING, RUNNABLE */
};

//	전체 스레드를 저장하는 공간
static task_struct_t all_thread[MAX_THREAD];

//	cpu에서 작동중인 스레드
task_struct_p current_thread;

//	context switching 이후 실행 할 스레드
task_struct_p next_thread;


extern void context_switch(void);

//	스레드 초기화
void thread_init(void)
{
  current_thread = &all_thread[0];
  current_thread->state = RUNNING;
}

//	스레드 스케줄링
static void __schedule(void)
{
  task_struct_p t;

  /* 다음 스레드를 찾음 */
  next_thread = 0;
  for (t = all_thread; t < all_thread + MAX_THREAD; t++) {
    if (t->state == RUNNABLE && t != current_thread) {
      next_thread = t;
      break;
    }
  }

  // 만약 다음 스레드를 못 찾으면 현재 스레드를 돌려줌
  if (t >= all_thread + MAX_THREAD && current_thread->state == RUNNABLE) {
    next_thread = current_thread;
  }

  if (next_thread == 0) {
    printf("다음 스레드가 없습니다. 종료합니다.\n");
    exit(1);
  }

  if (current_thread != next_thread) {         /* 다르면 context switch */
    next_thread->state = RUNNING;
    context_switch();
  } else
    next_thread = 0;
}

//	스레드 생성
void thread_create(void (*func)())
{
  task_struct_p t;

  for (t = all_thread; t < all_thread + MAX_THREAD; t++) {
    if (t->state == FREE) break;
  }
  t->sp = (int) (t->stack + STACK_SIZE);   // 스택 포인터는 각 스레드 가장 위쪽에 설정
  t->sp -= 4;                              // 리턴 주소 저장용으로 4 byte(32bit 머신) 빼기, 트릭
  * (int *) (t->sp) = (int)func;           // 현재 함수의 주소를 스택에 저장(방금전에 뺀)
  t->sp -= 32;                             // context switch를 위해 CPU 레지스터 저장공간을 비워둠
  t->state = RUNNABLE;
}

void schedule(void)
{
  current_thread->state = RUNNABLE;
  __schedule();
}

//	스레드를 인자로 받아 해당 스레드를 스케줄링 함
static void  mythread(void)
{
  int i;

  for (i = 0; i < 100; i++) {
    printf("thread 0x%x\n", (int) current_thread);
    schedule();
  }
  printf("thread: exit\n");
  current_thread->state = FREE;
  __schedule();
}


int main(int argc, char *argv[])
{
  thread_init();
  thread_create(mythread);
  thread_create(mythread);
  __schedule();

  return 0;
}

  • 처음 스레드를 생성하고 이를 RUNNING 상태로 설정
  • 스레드 목록 중 FREE인 것을 찾아 메모리 영역에 할당
  • 상태가 RUNNABLE인 스레드로 context_switching

0개의 댓글