`

Linux内核修改实验

阅读更多
Linux内核修改实验
实验目的:
1.      深入理解Linux启动过程;
2.      修改Linux内核,让Linux启动后不执行init进程,而执行自己编写的程序。
实验原理:
1.      Linux的启动有一个清晰的过程,基于Linux的开放性,修改其内核是完全可能的;
2.      当内核被引导并进行初始化之后,内核就可以启动自己的第一个用户空间应用程序init进程。
实验内容:
1.      Linux内核初始化过程
l        内核映像:
在Bootloader的第二阶段会调用内核镜像,当内核映像被加载到内存中,并且Bootloader阶段 2 的引导加载程序释放控制权之后,内核阶段就开始了。内核映像并不是一个可执行的内核,而是一个压缩过的内核映像。在这个内核映像前面是一个例程,它实现少量硬件设置,并对内核映像中包含的内核进行解压,然后将其放入高端内存中,如果有初始 RAM 磁盘映像,就会将它移动到内存中,并标明以后使用。然后该例程会调用内核,并开始启动内核引导的过程。
l        内核引导过程:
        当 bzImage(用于 i386 映像)被调用时,我们从 /XSBase255_Linux_C/Kernel/2.4.18-rmk7-pxa1-XSBase/arch/i386/boot/head.S 的 start 汇编例程开始执行。这个例程会执行一些基本的硬件设置,并调用 /arch/i386/boot/compressed/head.S 中的 startup_32 例程。此例程会设置一个基本的环境(堆栈等),并清除 Block Started by Symbol(BSS)。然后调用一个叫做 decompress_kernel 的 C 函数(在 /arch/i386/boot/compressed/misc.c 中)来解压内核。当内核被解压到内存中之后,就可以调用它了。这是另外一个 startup_32 函数,但是这个函数在 /arch/i386/kernel/head.S 中。
       在这个新的 startup_32 函数(也称为清除程序或进程 0)中,会对页表进行初始化,并启用内存分页功能。然后会为任何可选的浮点单元(FPU)检测 CPU 的类型,并将其存储起来供以后使用。然后调用 start_kernel 函数(在 init/main.c 中),它会将您带入与体系结构无关的 Linux 内核部分。实际上,这就是 Linux 内核的 main 函数。
    通过调用 start_kernel,会调用一系列初始化函数来设置中断,执行进一步的内存配置,并加载初始 RAM 磁盘。最后,要调用 kernel_thread(在 arch/i386/kernel/process.c 中)来启动 init 函数,这是第一个用户空间进程(user-space process)。最后,启动空任务,现在调度器就可以接管控制权了(在调用 cpu_idle 之后)。
l        深入分析内核源代码
    根据上面对内核引导过程的分析,我们可以进入Linux内核源代码跟踪其具体过程。这里我们将图示从./arch/i386/kernel/head.S的Startup_32开始的过程。
call SYMBOL_NAME(start_kernel)

head.S第270行 
        


asmlinkage void __init start_kernel(void)
./init/main.c第545行,函数最后(第628行)调用rest_init();
static void rest_init(void)
int kernel_thread(int (*fn)(void *),
void * arg, unsigned long flags)
./init/main.c第533行:
static void rest_init(void)
{
       kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
       unlock_kernel();
       current->need_resched = 1;
       cpu_idle();
}
 
 



























                            内核引导过程图示

                     在下一页我们可以看到kernel_thread函数的定义,我们关心的是                     rest_init函数中对kernel_thread的调用,从上面我们可以看到这样的语句:     
              kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
                     在这里,init当作函数指针传给kernel_thread,这样init将被执行,也就         成为Linux启动后第一个用户进程。可以设想,如果我们将自己的函数指针传        给kernel_thread,并作适当的初始化,就可以实现我们实验的目的。

/XSBase255_Linux_C/Kernel/2.4.18-rmk7-pxa1-XSBase/arch/i386/kernel/process.c第488行开始:
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
       long retval, d0;

       __asm__ __volatile__(
              "movl %%esp,%%esi\n\t"
              "int $0x80\n\t"            /* Linux/i386 system call */
              "cmpl %%esp,%%esi\n\t" /* child or parent? */
              "je 1f\n\t"             /* parent - jump */
              /* Load the argument into eax, and push it. That way, it does
               * not matter whether the called function is compiled with
               * -mregparm or not. */
              "movl %4,%%eax\n\t"
              "pushl %%eax\n\t"           
              "call *%5\n\t"             /* call fn */
              "movl %3,%0\n\t"      /* exit */
              "int $0x80\n"
              "1:\t"
              :"=&a" (retval), "=&S" (d0)
              :"0" (__NR_clone), "i" (__NR_exit),
               "r" (arg), "r" (fn),
               "b" (flags | CLONE_VM)
              : "memory");
       return retval;
}
 



















kernel_thread图示
2.      修改Linux内核,创建自己的init进程
      经过上面的分析,我们找到init的原型,它在main.c第85行:static int init(void *);
       它的定义在main.c的第805行,具体内容如下图示,



static int init(void * unused)
{
       lock_kernel();
       do_basic_setup();
       prepare_namespace();

       /*
        * Ok, we have completed the initial bootup, and
        * we're essentially up and running. Get rid of the
        * initmem segments and start the user-mode stuff..
        */

       free_initmem();
       unlock_kernel();
      

 
 




















if (open("/dev/console", O_RDWR, 0) < 0)
              printk("Warning: unable to open an initial console.\n");
       (void) dup(0);
       (void) dup(0);

/*
        * We try each of these until one succeeds.
        *
        * The Bourne shell can be used instead of init if we are
        * trying to recover a really broken machine.
        */

       if (execute_command)
              execve(execute_command,argv_init,envp_init);
       execve("/sbin/init",argv_init,envp_init);
       execve("/etc/init",argv_init,envp_init);
       execve("/bin/init",argv_init,envp_init);
       execve("/bin/sh",argv_init,envp_init);
       panic("No init found. Try passing init= option to kernel.");
}    
       
 

























init定义图示
              可以看到,init函数首先做一些基本的初始化设置,清除初始化过程用到的内      存空间后,就真正开始执行用户进程。首先尝试打开控制台,然后执行内核配置命令   行参数中给的程序,完成一些初始化工作。这里我们可以看到一个if语句,这个     execute_command是一个char* 类型的指针,在main.c中第426行的static void __init      parse_options(char *line)中,将命令行参数传给了它(第456行,execute_command=       line;)像我们在配置内核时,指定这样的字眼:    init=/linuxrc ,这样linuxrc就是在这       开始执行的,当然,它可能还会递归调用其它的需要执行的程序。如果没有设置参数,     就尝试执行指定的初始进程,这也是真正的用户进程了。在上面的定义中我们可以看 到,系统依次尝试执行/sbin/init,/ect/init/,/bin/init,/bin/sh进程,直到有一个运行成功;       如果全都执行失败,系统也就启动失败。
               下面开始我们的最终任务,那就是修改init,让系统启动时不执行/sbin/init。简单 的方法是先建立自己的可执行程序,如/sin/myinit,将init中对/sbin/init的调用改为对    /sbin/myinit的调用即可。
                这里给出本人对init的修改,新建自己的函数myinit,函数原型如下:
       static myint init(void *);//加至main.c头部,myinit定义如下,
       static int myinit(void * unused)
       {
       lock_kernel();
       do_basic_setup();

       prepare_namespace();

       free_initmem();
       unlock_kernel();

       if (open("/dev/console", O_RDWR, 0) < 0)
              printk("Warning: unable to open an initial console.\n");

       (void) dup(0);
       (void) dup(0);

       if (execute_command)
              execve(execute_command,argv_init,envp_init);
       execve("/sbin/myinit",argv_init,envp_init);
       panic("No init found. Try passing myinit= option to kernel.");
       }
            在/XSBase255_Linux_C/Filesystem/root_XSBASE/sbin新建可执行程序myinit,其源       文件定义如下:
//myinit.c
#include <stdio.h>
int main()
{
printf(“Haha,This is my init process!\n”;
}

           最后,转到/init/main.c第533行的rest_init(void)函数,修改其对          kernel_thread的调用如下,
       kernel_thread(myinit, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
                这样,我们就实现了内核启动的第一个用户进程是我们自己定义的myinit函数。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/DGerome/archive/2009/02/22/3920960.aspx
分享到:
评论

相关推荐

    setuptools-58.0.3.tar.gz

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    变压器DGA溶解气体数据(357组)

    包含六种故障类型: 中低温过热 高温过热 低能放电 高能放电 局部放电 正常 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111需要直接下载就可

    电抗器设计软件.zip

    电抗器设计软件

    base.apk

    base.apk

    SM4-CTS代码实现及基本补位示例代码

    代码参照openssl-3.3.0-alpha1,可独立运行。示例包含块加密,基本补位方式示例

    setuptools-60.3.0.tar.gz

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    setuptools-59.4.0.tar.gz

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    永宏 PLC例程17个.zip

    永宏 PLC例程17个

    电器工程配料及预算软件.zip

    电器工程配料及预算软件

    基于CS通信的五子棋游戏GoBang.zip

    五子棋游戏想必大家都非常熟悉,游戏规则十分简单。游戏开始后,玩家在游戏设置中选择人机对战,则系统执黑棋,玩家自己执白棋。双方轮流下一棋,先将横、竖或斜线的5个或5个以上同色棋子连成不间断的一排者为胜。 【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python、web、C#、EDA、proteus、RTOS等项目的源码。 【技术】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    python飞机大战Python_Airplane_War.zip

    五子棋游戏想必大家都非常熟悉,游戏规则十分简单。游戏开始后,玩家在游戏设置中选择人机对战,则系统执黑棋,玩家自己执白棋。双方轮流下一棋,先将横、竖或斜线的5个或5个以上同色棋子连成不间断的一排者为胜。 【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python、web、C#、EDA、proteus、RTOS等项目的源码。 【技术】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    setuptools-66.1.1.tar.gz

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    飞机大战PlaneGame.zip

    五子棋游戏想必大家都非常熟悉,游戏规则十分简单。游戏开始后,玩家在游戏设置中选择人机对战,则系统执黑棋,玩家自己执白棋。双方轮流下一棋,先将横、竖或斜线的5个或5个以上同色棋子连成不间断的一排者为胜。 【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python、web、C#、EDA、proteus、RTOS等项目的源码。 【技术】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    电气计算表格及小软件.zip

    电气计算表格及小软件

    ONNX模型转 TensorRT logging.h

    logging.h

    松下PLC例程55个.zip

    松下PLC例程55个

    setuptools-65.0.1.tar.gz

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    母亲节祝福html源码.pdf

    母亲节祝福html源码

    Theano-0.10.0b2.tar.gz

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    变压器铁心计算软件.zip

    变压器铁心计算软件

Global site tag (gtag.js) - Google Analytics