日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于mykernel完成多进程的简单内核

發(fā)布時間:2023/12/10 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于mykernel完成多进程的简单内核 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

學號351

?原創(chuàng)作品轉(zhuǎn)載請注明出處 +?https://github.com/mengning/linuxkernel/
  • mykernel簡介

mykernel是由孟寧老師建立的一個用于開發(fā)您自己的操作系統(tǒng)內(nèi)核的平臺,基于Linux Kernel 3.9.4?source code mykernel的源代碼?https://github.com/mengning/mykernel?,

你可以按照上面的指南部署到你的操作系統(tǒng),也可以使用實驗樓提供的虛擬機,該虛擬機上已經(jīng)部署好這個平臺,只需按照實驗二的步驟即可運行這個平臺框架。本文實驗完成于實驗樓。

具體操作:

cd LinuxKernel/linux-3.9.4

rm -rf mykernel

patch -p1 < ../mykernel_for_linux3.9.4sc.patch

make allnoconfig

make

qemu -kernel arch/x86/boot/bzImage

就可以在qemu上看到運行結果

如圖:

可以看出:

>>>>>>>>>>>>>>>my_timer_handler here<<<<<<<<<<和>>>>>>>>>>>>>>>my_start_kernel here<<<<<<<<<<<<<<<<會無限循環(huán)輸出。

接著查看mymian.c和myinterrupt.c文件

其中的my_start_kernel函數(shù)中有一個循環(huán),不斷輸出my_start_kernel here

有一個會被時鐘中斷周期調(diào)用的函數(shù)my_timer_handler。在這個函數(shù)里,會輸出類似>>>>>my_timer_handler here<<<<<?的字符串。

這兩個函數(shù)的輸出就是我們在窗口看到的內(nèi)容,

當mykernel系統(tǒng)啟動后,就會調(diào)用my_start_kernel函數(shù)(滿足條件i%10000==0),周期性調(diào)用my_timer_handler函數(shù)

  • 實現(xiàn)一個簡單的時間片輪轉(zhuǎn)多道程序

接下來我們通過擴展my_start_kernel和my_timer_handler函數(shù),模擬了一個基于時間片輪轉(zhuǎn)的多道程序。

1,實驗步驟:

(1)從實驗用的源代碼,https://github.com/mengning/mykernel通過git-clone命令下載到mykernel平臺。主要就這三個文件:mypcb.h,myinterrupt.c和mymain.c

(2)回到LinuxKernel/linux-3.9.4文件夾,使用下面的命令編譯、運行

具體操作如下:

cd ../ ??#回到linux-3.9.4目錄

make allnoconfig

make

qemu -kernel arch/x86/boot/bzImage

2,運行結果如圖:

3,源碼分析

mypcb. h:進程控制塊PCB結構體定義。

/** linux/mykernel/mypcb.h** Kernel internal PCB types** Copyright (C) 2013 Mengning**/#define MAX_TASK_NUM 4 #define KERNEL_STACK_SIZE 1024*2 # unsigned long /* CPU-specific state of this task */ struct Thread { //用于保存erp,espunsigned long ip;unsigned long sp; };typedef struct PCB{int pid;volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */unsigned long stack[KERNEL_STACK_SIZE];/* CPU-specific state of this task */struct Thread thread;unsigned long task_entry;struct PCB *next; }tPCB;void my_schedule(void);

其中各個字段含義如下:

pid:進程號

state:進程狀態(tài),在模擬系統(tǒng)中,所有進程控制塊信息都會被創(chuàng)建出來,其初始化值就是-1,如果被調(diào)度運行起來,其值就會變成0

stack:進程使用的堆棧

thread:當前正在執(zhí)行的線程信息

task_entry:進程入口函數(shù)

next:指向下一個PCB,模擬系統(tǒng)中所有的PCB是以鏈表的形式組織起來的。

my_schedule:函數(shù)聲明,在my_interrupt.c中實現(xiàn),在mymain.c中的各個進程函數(shù)會根據(jù)一個全局變量的狀態(tài)來決定是否調(diào)用它,從而實現(xiàn)主動調(diào)度。

?

mymain.c: 初始化各個進程并啟動0號進程。

/** linux/mykernel/mymain.c** Kernel internal my_start_kernel** Copyright (C) 2013 Mengning**/ #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include <linux/tty.h> #include <linux/vmalloc.h>#include "mypcb.h"tPCB task[MAX_TASK_NUM]; tPCB * my_current_task = NULL; volatile int my_need_sched = 0;void my_process(void);void __init my_start_kernel(void) {int pid = 0;int i;/* Initialize process 0*/task[pid].pid = pid;task[pid].state = 0;/* -1 unrunnable, 0 runnable, >0 stopped */task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process;task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1];task[pid].next = &task[pid];/*fork more process,每個進程都有自己的堆棧,并指向下一個進程 */for(i=1;i<MAX_TASK_NUM;i++){memcpy(&task[i],&task[0],sizeof(tPCB));task[i].pid = i;//*(&task[i].stack[KERNEL_STACK_SIZE-1] - 1) = (unsigned long)&task[i].stack[KERNEL_STACK_SIZE-1];task[i].thread.sp = (unsigned long)(&task[i].stack[KERNEL_STACK_SIZE-1]);task[i].next = task[i-1].next;task[i-1].next = &task[i];}/* 從第0個進程開始 */pid = 0;my_current_task = &task[pid];asm volatile("movl %1,%%esp\n\t" /* set task[pid].thread.sp to esp */"pushl %1\n\t" /* push ebp */"pushl %0\n\t" /* push task[pid].thread.ip */"ret\n\t" /* pop task[pid].thread.ip to eip */: : "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) /* input c or d mean %ecx/%edx*/); } int i = 0;void my_process(void) { while(1){i++;if(i%10000000 == 0){printk(KERN_NOTICE "this is process %d -\n",my_current_task->pid);if(my_need_sched == 1) //ny_need_sched=1時才會調(diào)度{my_need_sched = 0;my_schedule();}printk(KERN_NOTICE "this is process %d +\n",my_current_task->pid);} } }

系統(tǒng)啟動后,最先調(diào)用函數(shù)my_start_kernel,在這個函數(shù)里完成了0號進程的初始化和啟動,并創(chuàng)建了其它的進程PCB,以方便后面的調(diào)度。在模擬系統(tǒng)里,每個進程的入口函數(shù)都是 my_process,在執(zhí)行的時候,會打印出當前進程的 id。

另外,在 my_process 會檢查一個全局標志變量 my_need_sched,一旦發(fā)現(xiàn)其值為 1 ,就調(diào)用 my_schedule 完成進程的調(diào)度。

myinterrupt.c:時鐘中斷處理和進程調(diào)度算法。

/** linux/mykernel/myinterrupt.c** Kernel internal my_timer_handler** Copyright (C) 2013 Mengning**/ #include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include <linux/tty.h> #include <linux/vmalloc.h>#include "mypcb.h"extern tPCB task[MAX_TASK_NUM]; extern tPCB * my_current_task; extern volatile int my_need_sched; volatile int time_count = 0;/** Called by timer interrupt.* it runs in the name of current running process,* so it use kernel stack of current running process*/ void my_timer_handler(void) { #if 1if(time_count%1000 == 0 && my_need_sched != 1) //設置時間片大小,時間片用完設置調(diào)度標志{printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");my_need_sched = 1;} time_count ++ ; #endifreturn; }void my_schedule(void) {tPCB * next;把當前tPCB * prev;if(my_current_task == NULL || my_current_task->next == NULL){return;}printk(KERN_NOTICE ">>>my_schedule<<<\n");/* schedule */next = my_current_task->next; //把當前進程的下一個進程賦值給nextprev = my_current_task;if(next->state == 0)/* 下一個進程正在執(zhí)行*/{ my_current_task = next; printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid); /* switch to next process */asm volatile( //切換進程"pushl %%ebp\n\t" /* save ebp */"movl %%esp,%0\n\t" /* 把當前進程的esp賦給prev->thread.sp,保存*/"movl %2,%%esp\n\t" /* 把下一進程的next->thread.sp賦給esp */"movl $1f,%1\n\t" /* save eip */ "pushl %3\n\t" "ret\n\t" /*把下一進程的next->thread.ip進棧*/"1:\t" /* 下一進程開始執(zhí)行*/"popl %%ebp\n\t": "=m" (prev->thread.sp),"=m" (prev->thread.ip): "m" (next->thread.sp),"m" (next->thread.ip)); } return; }

內(nèi)核周期性調(diào)用my_timer_handler 函數(shù),每調(diào)用1000次,就去將全局變量my_need_sched的值修改為1,通知正在執(zhí)行的進程執(zhí)行調(diào)度程序my_schedule。在my_schedule函數(shù)中,完成進程的切換。

  • 總結

經(jīng)過該次試驗,我們對操作系統(tǒng)的進程調(diào)度機制和中斷機制有了更新的認識,也對之前學的內(nèi)容作了一次復習。Linux操作系統(tǒng)由內(nèi)核來實現(xiàn)它的具體工作的,系統(tǒng)通過調(diào)用fork()函數(shù)來創(chuàng)建的一個進程,他先是將先前CPU正在運行的進程的進程上下文保存在內(nèi)核態(tài)堆棧中,包括有eip,esp,ebp,cs等寄存器的數(shù)據(jù);然后加載創(chuàng)建的進程的上下文信息到相應的寄存器中,運行當前新建進程;運行完畢后根據(jù)系統(tǒng)的調(diào)度繼續(xù)執(zhí)行相應的進程。同時,操作系統(tǒng)以一種中斷的機制實現(xiàn)與用戶的交互。操作系統(tǒng)中的IDT描述好各個中斷對應的處理程序,當發(fā)生相對應的中斷時,由硬件來實現(xiàn)中斷信號的傳遞,CPU接收到相應的IRQ信號后,由操作系統(tǒng)如調(diào)度進程那樣調(diào)度相應的處理程序,來完成相應的中斷請求,實現(xiàn)與用戶的交互。

轉(zhuǎn)載于:https://www.cnblogs.com/ceciwang/p/10515223.html

總結

以上是生活随笔為你收集整理的基于mykernel完成多进程的简单内核的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。