一 实验过程
1 先进入LinuxKernel环境下,更新menu代码到最新版,用到的命令为rm menu -rf //强制删除当前menu,git clone http://git.shiyanlou.com/mengning/menu.git //重新克隆新版本的menu。make rootfs //rootfs是事先写好的一个脚本,自动编译自动生成根文件系统,同时自动启动MenuOS
2 test.c源代码修改如下:

include <stdio.h>

include <stdlib.h>

include "menu.h"

define FONTSIZE 10

int PrintMenuOS()  
{  
    int i, j;  
    char data_M[FONTSIZE][FONTSIZE] =  
    {  
        "          ",  
        "  *    *  ",  
        " ***  *** ",  
        " * *  * * ",  
        " * *  * * ",  
        " *  **  * ",  
        " *      * ",  
        " *      * ",  
        " *      * ",  
        "          "  
    };  
    char data_e[FONTSIZE][FONTSIZE] =  
    {  
        "          ",  
        "          ",  
        "    **    ",  
        "   *  *   ",  
        "  *    *  ",  
        "  ******  ",  
        "  *       ",  
        "   *      ",  
        "    ***   ",  
        "          "  
    };  
    char data_n[FONTSIZE][FONTSIZE] =  
    {  
        "          ",  
        "          ",  
        "    **    ",  
        "   *  *   ",  
        "  *    *  ",  
        "  *    *  ",  
        "  *    *  ",  
        "  *    *  ",  
        "  *    *  ",  
        "          "  
    };  
    char data_u[FONTSIZE][FONTSIZE] =  
    {  
        "          ",  
        "          ",  
        "  *    *  ",  
        "  *    *  ",  
        "  *    *  ",  
        "  *    *  ",  
        "  *    *  ",  
        "   *  **  ",  
        "    **  * ",  
        "          "  
    };  
    char data_O[FONTSIZE][FONTSIZE] =  
    {  
        "          ",  
        "   ****   ",  
        "  *    *  ",  
        " *      * ",  
        " *      * ",  
        " *      * ",  
        " *      * ",  
        "  *    *  ",  
        "   ****   ",  
        "          "  
    };  
    char data_S[FONTSIZE][FONTSIZE] =  
    {  
        "          ",  
        "    ****  ",  
        "   **     ",  
        "  **      ",  
        "   ***    ",  
        "     **   ",  
        "      **  ",  
        "     **   ",  
        "  ****    ",  
        "          "  
    };  
  
    for(i=0; i<FONTSIZE; i++)  
    {  
        for(j=0; j<FONTSIZE; j++)  
        {  
            printf("%c", data_M[i][j]);  
        }  
        for(j=0; j<FONTSIZE; j++)  
        {  
            printf("%c", data_e[i][j]);  
        }  
        for(j=0; j<FONTSIZE; j++)  
        {  
            printf("%c", data_n[i][j]);  
        }  
        for(j=0; j<FONTSIZE; j++)  
        {  
            printf("%c", data_u[i][j]);  
        }  
        for(j=0; j<FONTSIZE; j++)  
        {  
            printf("%c", data_O[i][j]);  
        }  
        for(j=0; j<FONTSIZE; j++)  
        {  
            printf("%c", data_S[i][j]);  
        }  
        printf("\n");  
    }  
    return 0;  
}  
  
int Quit(int argc, char argv[])  
{  
    /
 add XXX clean ops */  
    exit(0);  
}

include <sys/stat.h>

include <sys/types.h>

...
int MakeDir() {
int ret = 0;
ret = mkdir("./testdir", 0777);
printf("ret is: %d.\n", ret);
return 0;
}

int MakeDirAsm() {
int ret = 0;
//ret = mkdir("./testdir", 0777);
char *dir = "./testdir";
int mode = 0777;
asm volatile(
"movl %1, %%ebx\n\t"
"movl %2, %%ecx\n\t"
"movl $39, %%eax\n\t"
"int $0x80\n\t"
"movl %%eax, %0\n\t"
: "=m"(ret)
: "m"(dir), "m"(mode)
);
printf("ret is: %d.\n", ret);
return 0;
}
int main()  
{  
    PrintMenuOS();  
    SetPrompt("MenuOS>>");  
    MenuConfig("version","XXX V1.0(Menu program v1.0 inside)",NULL);  
    MenuConfig("quit","Quit from XXX",Quit);  
   MenuConfig("make-dir","Make Directory",MakeDir);
MenuConfig("make-dir-asm","Make Directory(asm)",MakeDirAsm);   
    ExecuteMenu();  
}  
代码添加完成后make rootfs重新编译,此时系统会自动启动。如下图:

其增加了相应功能

3 执行以下命令开启内核的调试功能 qemu -kernel linux-3.18.6/arch/x86/boot/bz/Image -initrd rootfs.img -s -S,此时系统处于停止状态

其增加了相应功能

4重启内核调用
$ cd /home/shiyanlou/LinuxKernel
$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
再打开一个命令行窗口输入gdb,在gdb命令提示符下依次输入file linux-3.18.6/vmlinux, target remote:1234命令连接内核并跟踪调试,设置断点break sys_getpid, 接着continue开始运行,此时menuOS从stopped状态开始执行。在menu程序的提示符下输入who,程序执行到断点时暂停,此时gdb窗口显示程序断在sys_getpid处,接着使用gdb单步执行命令。next:不进入函数体的单步执行;step:进入函数体的单步执行;finish:进入函数体后退回调用函数
二 课本知识
同步的概念
临界区:也称为临界段,就是访问和操作共享数据的代码段。
竞争条件: 2个或2个以上线程在临界区里同时执行的时候,就构成了竞争条件。
所谓同步,其实防止在临界区中形成竞争条件。
如果临界区里是原子操作(即整个操作完成前不会被打断),那么自然就不会出竞争条件。但在实际应用中,临界区中的代码往往不会那么简单,所以为了保持同步,引入了锁机制。但又会产生一些关于锁的问题。
死锁产生的条件:要有一个或多个执行线程和一个或多个资源,每个线程都在等待其中的一个资源,但所有资源都已被占用。所以线程相互等待,但它们永远不会释放已经占有的资源。于是任何线程都无法继续,死锁发生。
自死锁:如果一个执行线程试图去获得一个自己已经持有的锁,它不得不等待锁被释放。但因为它正在忙着等待这个锁,所以自己永远也不会有机会释放锁,死锁产生。
饥饿(starvation) 是一个线程长时间得不到需要的资源而不能执行的现象
同步的方法
原子操作
原子操作指的是在执行过程中不会被别的代码路径所中断的操作,内核代码可以安全的调用它们而不被打断。
原子操作分为整型原子操作和位原子操作。
spinlock自旋锁
自旋锁的特点就是当一个线程获取了锁之后,其他试图获取这个锁的线程一直在循环等待获取这个锁,直至锁重新可用。
由于线程实在一直循环的获取这个锁,所以会造成CPU处理时间的浪费,因此最好将自旋锁用于能很快处理完的临界区。

posted on 2017-11-06 01:21  9225王孟亚  阅读(93)  评论(1编辑  收藏  举报