내가 운영 체제 (VI)를 작성하는 방법을 학습했다 : 예약 프로세스

머리말

멀티 프로세스의 도입은, 사실, 앞뒤로 과정 사이를 전환 할 수 있기 때문에, 프로세스 간의 스케줄링 문제가있을 수 있습니다. 그러나 실제로 실행 가능한 프로세스 사이의 제한된 자원 커널 서브 시스템 프로세서 시간의 할당이다.

몇 가지 간단한 CPU 스케줄링 알고리즘

  • 먼저 첫 번째 봉사, (FCFS)를 가자

그것은 실제로 FIFO 큐, 우선 첫째, 올 구현되는 과정입니다. CPU가 유휴 상태 일 때,이 프로세스가 큐의 선두에 위치에 할당하고,이 프로세스는 큐에서 제거되고 실행됩니다. FCFS 스케줄링을 간단하고 쉽게 이해 코딩.

처리 시간은 전체 작업 큐를 완료하는 데 필요한 기 때문에 프로세스 및 사용자 상호 작용에 대한 필요성이 스케줄링 알고리즘은 매우 긴, 아주 나쁜 경험을 발생합니다

그러나, FCFS 스케줄링 알고리즘 비 선점이다. 는 CPU가 방출, 즉, 프로그램 종료 요구 또는 I / O.까지 CPU까지 CPU를 사용하는 프로세스에 할당되면

  • 최단 작업 우선 (SJF)

알고리즘이 작동합니다 SJF 스케줄링이 짧거나 짧은 프로세스 우선 순위 스케줄링 알고리즘을 의미, 각 프로세스는 운영에 예상 시간 작업을 계산하기 위해 짧은 시간과 관련된 자사의 추정치를 실행합니다. 이 처리 시간을 줄일 수 있습니다

최단 제 작업 (SJF) 스케줄링 알고리즘은 그 다음 CPU의 길이가 각 프로세스를 실행 연관. CPU가 유휴 상태가되면, 최단 CPU에 의해 실행으로 처리를 할당한다. FCFS는 CPU에 의해 처리 될 수있는 경우에 실행되도록 두 개의 프로세스는 동일한 길이를 갖는다.

  • RR

이 알고리즘에서, 짧은 시간 단위는 시간 슬라이스 또는 시간의 양으로 정의된다. 타임 슬라이스 크기는 일반적으로 10 ~ 100ms에 있습니다. 순환 큐 준비 완료 큐. 스케줄러 루프의 CPU의 전체 준비 큐, 각 프로세스에 대한 더 이상의 할당 된 CPU의 타임 슬라이스.

RR 스케줄링을 구현하기 위해, 우리는 다시 한 번 준비 큐 FIFO 큐의 프로세스로 처리됩니다. 새로운 프로세스가 준비 큐의 말미에 추가됩니다. CPU 스케줄러가 대기 큐에 제 프로세스를 선택하고, 타임 슬라이스 한 후, 타이머 인터럽트를 설정하고, 마지막으로 프로세스 디스패치.

타협 스케줄링 알고리즘

많은 프로세스에서 실행, 일부는 공정 응답 시간에 대한 더 많은 관심을, 그리고 스케줄링 알고리즘 타협 할 필요가 있으므로 일부, 처리 시간의 과정에 더 많은 관심을하지만, 타협 방법에 대한 질문입니다.

Linux0.11 스케줄링 알고리즘

시간표

Linux0.11 일정 스케줄링 알고리즘에서 가장 중요한,하지만 매우 간단합니다

  • 된 task_struct 구조의 처리를 설명하는 데 사용되는

    카운터의 task_struct 스케줄링 알고리즘은 시간 분할 할당하고, 처리의 우선 순위를 나타내는 데 사용 나타내는데 사용되는 키 손상, 둘 다

  • 작업에서 작업의 배열이 시작에서 첫 번째, 마지막 사이클은 일부 필드를 감지

    타이밍이 너무 알람 작업 설정하고, (알람 <jiffies 단위) 만료 된 경우, 중앙 신호 전송 SIGALARM의 SIGALRM 신호 비트 맵, 즉 작업. 그런 다음 알람을 해제. 나중에 언급 할 것이다 금액에 관련된 일부 신호가있다

  • 프로세스의 최소 실행 시간 인 couter의 최대치를, 그 전환 과정 찾기

  • 시간 슬롯을 할당 재 다시 회전의 이행이 완료되면, 회전이 시간 진행, 타임 슬라이스가 초기 값으로 설정한다되었지만 프로세스 차단 사람들을 위해 수행되는 타임 슬라이스를 증가 타협 스케줄링.

void schedule(void)
{
    int i,next,c;
    struct task_struct ** p;

/* check alarm, wake up any interruptible tasks that have got a signal */

    for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
        if (*p) {
            if ((*p)->alarm && (*p)->alarm < jiffies) {
                    (*p)->signal |= (1<<(SIGALRM-1));
                    (*p)->alarm = 0;
                }
            if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
            (*p)->state==TASK_INTERRUPTIBLE)
                (*p)->state=TASK_RUNNING;
        }

/* this is the scheduler proper: */

    while (1) {
        c = -1;
        next = 0;
        i = NR_TASKS;
        p = &task[NR_TASKS];
        while (--i) {
            if (!*--p)
                continue;
            if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
                c = (*p)->counter, next = i;
        }
        if (c) break;
        for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
            if (*p)
                (*p)->counter = ((*p)->counter >> 1) +
                        (*p)->priority;
    }
    switch_to(next);
}

초기화

우리가 sched_init 보는 방식으로,이 초기화 루틴 커널 스케줄러 기능이 일부 중단 및 기술자를 초기화하는 것입니다

  • 첫 번째 통화 set_tss_desc 및 프로세스의 TSS와 LDT 0 set_ldt_desc 세트

  • 명확한 임무와 배열 설명 테이블 항목

  • 초기화 8253 타이머 후

  • 마지막으로, 클럭 인터럽트를 설정하고 시스템 호출을 중단

void sched_init(void)
{
    int i;
    struct desc_struct * p;

    if (sizeof(struct sigaction) != 16)
        panic("Struct sigaction MUST be 16 bytes");
    set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
    set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
    p = gdt+2+FIRST_TSS_ENTRY;
    for(i=1;i<NR_TASKS;i++) {
        task[i] = NULL;
        p->a=p->b=0;
        p++;
        p->a=p->b=0;
        p++;
    }
/* Clear NT, so that we won't have troubles with that later on */
    __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
    ltr(0);
    lldt(0);
    outb_p(0x36,0x43);      /* binary, mode 3, LSB/MSB, ch 0 */
    outb_p(LATCH & 0xff , 0x40);    /* LSB */
    outb(LATCH >> 8 , 0x40);    /* MSB */
    set_intr_gate(0x20,&timer_interrupt);
    outb(inb_p(0x21)&~0x01,0x21);
    set_system_gate(0x80,&system_call);
}

설정 설명자

이 동작은 실제로 _set_tssldt_desc 각 비트 세트 설명입니다

#define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),((int)(addr)),"0x89")
#define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),((int)(addr)),"0x82")

#define _set_tssldt_desc(n,addr,type) \
__asm__ ("movw $104,%1\n\t" \
    "movw %%ax,%2\n\t" \
    "rorl $16,%%eax\n\t" \
    "movb %%al,%3\n\t" \
    "movb $" type ",%4\n\t" \
    "movb $0x00,%5\n\t" \
    "movb %%ah,%6\n\t" \
    "rorl $16,%%eax" \
    ::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
     "m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
    )

설정 인터럽트

#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ ("movw %%dx,%%ax\n\t" \
    "movw %0,%%dx\n\t" \
    "movl %%eax,%1\n\t" \
    "movl %%edx,%2" \
    : \
    : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
    "o" (*((char *) (gate_addr))), \
    "o" (*(4+(char *) (gate_addr))), \
    "d" ((char *) (addr)),"a" (0x00080000))

#define set_intr_gate(n,addr) \
    _set_gate(&idt[n],14,0,addr)

#define set_system_gate(n,addr) \
    _set_gate(&idt[n],15,3,addr)    

개요

이는 주요 스케줄링 알고리즘, 아주 간단한에서 Linux0.11을 보였다이지만, 응답 시간 처리 할뿐만 아니라 또한 처리 시간을 돌볼 것입니다.

그리고 이전의 설정에 따라, 사실, 조금 초기화 루틴 커널 스케줄러를 넣어 일부 기술자 말과 인터럽트 처리

추천

출처www.cnblogs.com/secoding/p/11422525.html