Я научиться писать операционную систему (VI): процесс планирования

предисловие

Так как введение мульти-процесс, на самом деле, чтобы переключаться между процессом, будет проблема планирования между процессами. Но в действительности является распределением ограниченного ядра ресурсов времени подсистемы процессора между запускаемыми процессами.

Несколько простых алгоритм планирования CPU

  • First Come, First Served (FCFS)

Это на самом деле очередь FIFO, процесс, который первым пришел, первым реализован. Когда процессор находится в режиме ожидания, оно будет направлено на процесс находится в голове очереди, и запустить этот процесс удаляется из очереди. FCFS планирование кодирования простого и легко понять.

Но необходимость взаимодействия процесса и пользователя, этот алгоритм планирования приведет к очень плохой опыт, потому что оборотное время, необходимое для завершения целой очереди задач очень долго

Тем не менее, алгоритм планирования FCFS не является упреждающим. После того, как центральный процессор назначается к процессу, который будет использовать процессор до процессора до выхода, то есть, запрос завершения программы или ввода / вывода

  • Кратчайший Работа First (SJF)

SJF алгоритм планирование будет работать относится к короткому или короткому алгоритму приоритета процесса планирования, каждый процесс будет работать свою оценку, связанную с самым коротким временем, чтобы вычислить оцененное рабочее время в эксплуатацию. Это может уменьшить время обработки

Кратчайший работу первого (SJF) алгоритм планирования, длина его следующего CPU выполняет ассоциировать каждый процесс. Когда процессор переходит в режим ожидания, то он будет присвоен процесс с самым коротким выполняется процессором. Так что если FCFS могут быть обработаны с помощью ЦПУ выполняет два процесса имеют одинаковую длину.

  • RR

В этом алгоритме, небольшая единица времени определяется как промежуток времени или временной срез. Время размер среза обычно составляет 10 ~ 100 мс. Готовые очереди как круговая очередь. CPU всех готовые очереди цикла планировщика, не более чем один назначается CPU квант времени для каждого процесса.

Для осуществления планирования RR, мы будем еще раз рассматривать как процесс очереди FIFO готова очереди. Новый процесс добавлен к хвосту готовой очереди. CPU планировщик выбирает первый процесс из очереди готовой, установить прерывание таймера после временного отрезка, и, наконец, диспетчерский процесс.

Алгоритм планирования Компромисс

Во многих процессах работает, и некоторые из них больше озабочены временем отклика процесса, и некоторые из них больше озабочены процессом межремонтного, поэтому алгоритмы планирования нужно идти на компромисс, но компромисс является вопрос о том, каким образом.

Алгоритм планирования Linux0.11

график

График Linux0.11 является наиболее важным в алгоритме планирования, но очень простой

  • task_struct используется для описания процесса, структуры

    Алгоритм планирования счетчика task_struct является одним из ключевого компромисса, и используется для представления квантого времени выделена и используются для представления приоритета процесса

  • Во-первых, из массива задач в задаче начинается последний цикл обнаружения некоторых полей

    Если сроки слишком параметры задачи сигнализации, и истекло (сигнализация <тиков), центральный сигнал передачи SIGALARM SIGALRM сигналов растровых изображений, а именно задача. Тогда ясно, сигнализация. Есть некоторые сигналы, связанные с количеством упомянет позже

  • Найти максимальное значение противоионов, что является минимальным временем работы процесса, процесс перехода к ней

  • После завершения реализации задней ротации повторно выделена временной интервал, на этот раз для вращения был достигнут прогресс, квант времени будет установлен в начальное значение, но и для тех, кто блокировал процесс, приведет к увеличению времени среза, который осуществляется компромисс планирования.

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 вызов и set_ldt_desc набор процессов TSS и LDT 0

  • Очистить мандат и элемент массива таблица дескрипторов

  • После того, как таймер инициализации 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 Descriptor

Действие на самом деле _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