23.12.04 최초 작성
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_FIFO | SCHED_RR | SCHED_OTHER | SCHED_BATCH | SCHED_IDLE |
|---|---|---|---|---|
| First in First out | Round 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
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
#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