linux內和分析之sched c程式

2021-04-20 06:25:05 字數 4598 閱讀 5412

該核心程式主要包含程序排程程式的實現。程序排程採用了基於優先順序的時間片輪轉演算法。

#include

#include

#include

#include

#include

#include

#include

#include

這是乙個巨集,用來取得訊號的二進位制數值。

輸入:訊號編號,1-32

輸出:訊號的二進位制數值

#define _s(nr) (1<<((nr)-1))

被阻塞的訊號掩碼,其中有兩個訊號不能被阻塞sigkll和sigstop。這兩個訊號的

位為0,其他位為1 

#define _blockable (~(_s(sigkill) | _s(sigstop)))

顯示制定任務的資訊:包括程序id,任務號,任務當前狀態以及指定任務核心態堆疊空閒的位元組數

void

show_task (int nr, struct task_struct *p)

列印所有任務的資訊

nr_tasks表示系統允許的最大任務數量

void

show_stat (void)

#define latch (1193180/hz)

申明外部定義的函式。

extern void mem_use (void); 

extern int timer_interrupt (void); 

extern int system_call (void); 

乙個聯合體,該聯合體既可以用位元組形式表示,也可以用任務結構表示。

我們知道乙個任務的核心堆疊大小是4kb,即一頁大小。

union task_union

;定義初始化任務陣列

static union task_union init_task = ; 

定義變數,從開機起經過的滴答數,10ms為乙個滴答,將變數申明為volatile是因為

防止編譯器優化而導致的變數值不一致的情況。優化後變數值很有可能直接來自暫存器

我們使用此變數申明修飾符,保證每次從記憶體中取變數的值。

long volatile jiffies = 0; 

從開機後經歷的秒數。從2023年1月1日0時開始計算。

long startup_time = 0;  

初始化當前任務指標。

struct task_struct *current = &(init_task.task);

使用過協處理器的任務指標 

struct task_struct *last_task_used_math = null;

初始化任務陣列 

struct task_struct *task[nr_tasks] = ;

定義任務堆疊,大小為1024個4位元組的項組成。 

long user_stack[page_size >> 2]; 

定義核心資料段的乙個結構體,該結構體中包括

乙個核心堆疊指標和乙個段選擇符

0x10:核心資料段段選擇符

struct

stack_start =

;當任務發生切換的時候,用來儲存上乙個任務的協處理器上下文環境,恢復當前任務的

協處理器上下文環境。

void

math_state_restore ()

並置上次換出任務指標為當前任務

last_task_used_math = current; 

判斷當前任務是否使用了協處理器,如果是恢復協處理器的上下文。如果是

第一次使用,需要進行協處理器初始化工作。

if (current->used_math)

else

}核心程序排程程式

void

schedule (void)

如果訊號點陣圖中表示有非阻塞訊號被遞送,該任務的狀態是可中斷的,那麼將該任務狀態置為就緒

if (((*p)->signal & ~(_blockable & (*p)->blocked)) &&

(*p)->state == task_interruptible)

(*p)->state = task_running; 

}檢查就緒的任務,判斷下乙個執行的任務。

while (1)

如果最大時間片不為0,那麼就切換到該任務去執行

if (c)

break;

如果所有任務的時間片都為0,那麼重新計算各個任務的時間片,計算原則是根據優先順序進行計算

然後從新選擇時間片最大的任務去執行。

for (p = &last_task; p > &first_task; --p)

if (*p)

(*p)->counter = ((*p)->counter >> 1) + (*p)->priority;

}任務切換

switch_to (next);  

}將該任務置為可中斷狀態,然後執行任務排程程式

intsys_pause (void)

在指定任務上睡眠,任務0不能睡眠。如果cpu上沒有任務執行時就執行任務0,該函式是

不可中斷的。

void

sleep_on (struct task_struct **p)

該函式與上面的那個sleep函式的區別在於,如果下次再次排程到

睡眠的程序的時候,判斷如果當前程序是睡眠的程序,需要重新進行

排程。void

interruptible_sleep_on (struct task_struct **p)

*p = null;

if (tmp)

tmp->state = 0;

}將任務陣列中的任務置為就緒喚醒狀態,然後置該任務陣列項為0.

void

wake_up (struct task_struct **p)

}定義了timer list的最大長度

#define time_requests 64 

定義timer list結構

static struct timer_list

timer_list[time_requests], *next_timer = null;

加入定時器

void add_timer (long jiffies, void (*fn) (void))

}開啟可遮蔽中斷

sti ();

}時鐘中斷處理函式呼叫此c函式。

void

do_timer (long cpl)

}這部分是對軟碟機的處理,在這裡不講

if (current_dor & 0xf0)

do_floppy_timer ();

if ((--current->counter) > 0)

return;   

current->counter = 0;

if (!cpl)

return;

中斷執行完成,重新排程任務  

schedule ();

}設定定時器,返回上次設定的定時器剩餘的秒數

將新的秒數轉換成滴答數,設定到當前程序中去

intsys_alarm (long seconds)

intsys_getpid (void)

取程序id

intsys_getppid (void)

取使用者id

intsys_getuid (void)

取有效使用者id

intsys_geteuid (void)

取組id

intsys_getgid (void)

取有效組id

intsys_getegid (void)

設定程序nice值,即降低優先順序

intsys_nice (long increment)

在main.c中呼叫,對schedle進行初始化。

void

sched_init (void)

desc_table[256];

一共256項。

確定描述符標的偏移值。之前設定過tss和第乙個ldt的描述符。

為任務陣列清0,將128個描述符表項清0

p = gdt + 2 + first_tss_entry;

for (i = 1; i < nr_tasks; i++)

清除標誌暫存器中的nt標誌位,巢狀標誌位,如果中斷處理程式呼叫iret指令,就會引起任務切換

__asm__ ("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); 

將任務0的任務狀態段的選擇符加入到任務暫存器中

ltr (0);   

將任務0的區域性表選擇符載入到區域性描述符暫存器中。

lldt (0);   

初始化定時器。

outb_p (0x36, 0x43);  

outb_p (latch & 0xff, 0x40); 

outb (latch >> 8, 0x40); 

set_intr_gate (0x20, &timer_interrupt);

outb (inb_p (0x21) & ~0x01, 0x21);

set_system_gate (0x80, &system_call);

}

Mysql 外連線和內連線分析

表1 test user 表2 一 left join 2 select from test user a left join test order b on a.name b.namewhere a.name 張三 3 select from test user a left join test ...

linux核心分析之fork c

include include include include include 申明外部呼叫函式,驗證位址所指向的頁面是否可寫 extern void write verify unsigned long address 全域性變數,用於產生可用的程序id long last pid 0 對指定起始...

linux核心分析之sys c

include include include include include include include 這個檔案中包含了絕大部分系統呼叫函式的實現,如果系統呼叫在該核心版本中沒實現,就直接返回enosys int sys ftime int sys break int sys ptrace ...