群辉nas怎么做网站,自己做头像的网站漫画,优化一个网站需要多少钱,深圳网站建设有免费的吗秦鼎涛 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000  一、实验目的及要求#xff1a; 使用gdb跟踪调试内核从start_kernel到init进程启动  详细分析从start_kernel到init进程启动的过程并结合实验截图撰写一篇署名博客#xff0c;并在博客文…秦鼎涛 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000  一、实验目的及要求  使用gdb跟踪调试内核从start_kernel到init进程启动  详细分析从start_kernel到init进程启动的过程并结合实验截图撰写一篇署名博客并在博客文章中注明“真实姓名与最后申请证书的姓名务必一致  原创作品转载请注明出处  《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”博客内容的具体要求如下  题目自拟内容围绕Linux内核的启动过程即从start_kernel到init进程启动  博客中需要使用实验截图  博客内容中需要仔细分析start_kernel函数的执行过程  总结部分需要阐明自己对“Linux系统启动过程”的理解尤其是idle进程、1号进程是怎么来的。  3请提交博客文章URL到网易云课堂MOOC平台Linux内核分析MOOC课程编辑成一个链接可以直接点击打开。   二、实验步骤含实验楼截图   1、登陆实验楼虚拟机      打开shell终端执行以下命令     cd LinuxKernel/     qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootfs.img      系统支持三个命令help、version、quit   2、使用gdb跟踪调试内核   执行以下命令    cd LinuxKernel/   qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootfs.img -s -S   关于-s和-S选项的说明   -S freeze CPU at startup (use ’c’ to start execution) 在系统启动的时候冻结CPU使用c键继续执行后续操作   -s shorthand for -gdb tcp::1234 打开远程调试端口默认使用tcp协议1234端口若不想使用1234端口则可以使用-gdb tcp:xxxx来取代-s选项            打开另外一个shell终端执行以下命令    gdb    gdbfile linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表    gdbtarget remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行    gdbbreak start_kernel # 断点的设置可以在target remote之前也可以在之后      不知道为什么没有找到文件目录。。   三、start_kernel函数的执行过程分析 asmlinkage void __init start_kernel(void) { char * command_line; extern struct kernel_param __start___param[], __stop___param[];/* * Interrupts are still disabled. Do necessary setups, then * enable them */ lock_kernel(); 如果内核配置成支持抢占那么在这里禁止抢占将0号进程的init_thread_info.preempt_count加1 如果配置成不支持抢占那么内核全局自选锁kernel_flag上锁。 page_address_init(); 10版本的ARM部分没有支持高端内存相关代码空函数。 printk(linux_banner); 将linux_banner的内容打印到log_buf缓冲区中。 setup_arch(command_line); 函数原型在arch/arm/kernel/setup.c中 根据处理器、硬件平台具体型号设置系统。解析Linux系统命令行设置0号进程swapper进程的内存描述结构init_mm系统内存管理初始化统计并注册系统各种资源其他项目的初始化。 setup_per_cpu_areas(); 为系统中每个处理器的per_cpu变量申请空间。 /*  * Mark the boot cpu online so that it can call console drivers in  * printk() and can access its per-cpu storage.  */ smp_prepare_boot_cpu(); /*  * Set up the scheduler prior starting any interrupts (such as the  * timer interrupt). Full topology setup happens at smp_init()  * time - but meanwhile we still have a functioning scheduler.  */ sched_init(); 初始化每个处理器的可运行进程队列设置系统初始化进程即0号进程。 build_all_zonelists(); 建立系统内存页区zone链表。 page_alloc_init(); printk(Kernel command line: %s\n, saved_command_line); parse_early_param(); 解析早期格式内核参数。 parse_args(Booting kernel, command_line, __start___param,     __stop___param - __start___param,     unknown_bootoption); 解析新格式内核参数。 sort_main_extable(); 将放在__start__ex_table到__stop__ex_table之间的*(__ex_table)区中的struct exception_table_entry型全局结构变量按insn成员变量值从小到大排序即将可能导致缺页异常的指令按其指令二进制代码值从小到大排序。 trap_init(); 把放在.Lcvectors处的系统8个意外的入口跳转指令搬到高端中断向量0xffff0000处再将从__stubs_start到__stubs_end之间的各种意外初始处理代码搬到0xffff0200处。刷新0xffff0000处1页范围的指令cache,将DOMAIN_USER的访问权限由DOMAIN_MANAGER权限改设置成DOMAIN_CLIENT权限。 rcu_init(); 初始化当前CPU的读、复制、更新数据结构(struct rcu_data)全局变量per_cpu_rcu_data和per_cpu_rcu_bh_data。 init_IRQ(); 初始化系统中支持的最大可能中断数的中断描述结构struct irqdesc变量数组irq_desc[NR_IRQS]把每个结构变量irq_desc[n]都初始化为预先定义好的坏中断描述结构变量bad_irq_desc并初始化该中断的连表表头成员结构变量pend. pidhash_init(); 设置系统中每种pid hash表中的hash链表数的移位值全局变量pidhash_shift将pidhash_shift设置为min(12);分别为每种hash表的连续hash链表表头结构空间申请内存把申请到的内存虚拟基址分别传给pid_hash[n](n0~3),并将每种hash表中的每个hash链表表头结构struct hlist_head中的first成员指针设置成NULL init_timers(); 初始化当前出处理器的时间向量基本结构struct tvec_t_base_s全局变量per_cpu_tvec_bases,初始化per_cpu_tvec_bases的自旋锁成员变量lock。 softirq_init(); 设置系统小任务软件中断行为函数描述结构变量softirq_vec[TASKLET_SOFTIRQ(6)],将softirq_vec[6]的行动函数指针action指向tasklet_action()函数参数指针设置为NULL. time_init(); 检查系统定时器描述结构struct sys_timer全局变量system_timer是否为空如果是将其指向dummy_gettimeoffset()函数。 /*  * HACK ALERT! This is early. Were enabling the console before  * weve done PCI setups etc, and console_init() must be aware of  * this. But we do want output early, in case something goes wrong.  */ console_init(); 初始化系统的控制台结构该函数执行后调用printk()函数将log_buf中符合打印级别要求的系统信息打印到控制台上。 if (panic_later)  panic(panic_later, panic_param); profile_init(); 对系统剖析作相关初始化系统剖析用于系统调用。 local_irq_enable(); 将处理器的当前系统状态寄存器CPSR的第7位清0使能IRQ中断。#ifdef CONFIG_BLK_DEV_INITRD if (initrd_start  !initrd_below_start_ok    initrd_start  min_low_pfn  PAGE_SHIFT) {  printk(KERN_CRIT initrd overwritten (0x%08lx  0x%08lx) -       disabling it.\n,initrd_start,min_low_pfn  PAGE_SHIFT);  initrd_start  0; }#endif vfs_caches_init_early(); mem_init(); 该函数执行完后不能再用像alloc_bootmem()、alloc_bootmem_low()、alloc_bootmem_pages()等申请低端内存的函数来申请内存也就不能申请大块的连续物理内存了。 kmem_cache_init(); 执行高速缓存内存管理即slab分配器相关初始化。 numa_policy_init(); if (late_time_init)  late_time_init(); calibrate_delay(); 计算机系统的BogMIPS数值即处理器每秒钟执行的指令数。 pidmap_init(); pgtable_cache_init(); prio_tree_init(); 初始化无符号长整型全局数组index_bits_to_maxindex[BITS_PER_LONG]的每个组员将每个组员index_bits_to_maxindex[n]设置成-1,将最后的index_bits_to_maxindex[BITS_PER_LONG-1]设置成0UL。 anon_vma_init(); 该函数调用kmem_cache_create函数为匿名虚拟内存区域链表结构struct anon_vma创建高速缓存内存描述结构kmem_cache_t变量为该变量命名为“anon_vma其对象的构造函数指针指向void anon_vma_ctor(void *data,kmem_cache_t *cachep,unsigned long flags)函数析构函数指针空将创建的kmem_cache_t结构变量地址传给全局指针anon_vma_chachep。#ifdef CONFIG_X86 if (efi_enabled)  efi_enter_virtual_mode();#endif fork_init(num_physpages); 执行进程创建相关初始化。 proc_caches_init(); buffer_init(); 调用 kmem_cache_create(buffer_head, sizeof(struct buffer_head), 0, SLAB_PANIC, init_buffer_head, NULL)函数为缓冲区描述结构struct buffer_head创建高速缓存内存描述结构kmem_cache_t变量。 unnamed_dev_init(); 调用并返回idr_init(unnamed_dev_idr)函数。 security_init(); 打印”安全架构v1.0.0被初始化“。如果没有定义系统哑元安全操作函数组结构全局变量dummy_security_ops,打印错误信息返回I/O错误。 vfs_caches_init(num_physpages); radix_tree_init(); signals_init(); 调用kmem_cache_create(sigqueue, sizeof(struct sigqueue), __alignof__(struct sigqueue), SLAB_PANIC, NULL, NULL)函数为信号队列结构struct sigqueue创建高速缓存内存描述结构kmem_cache_t变量名字叫”sigqueue“不要求其对象按处理器硬件cache line大小对齐没有定义其对象的构造和析构函数将创建号的kmem_cache_t结构变量的地址传给全局指针sigqueue_cachep。 /* rootfs populating might need page-writeback */ page_writeback_init(); 统计系统中所有内存节点的通用(NORMAL)内存页区中高页数水印值页数之外的额外内存总页数之和传给buffer_pages。#ifdef CONFIG_PROC_FS proc_root_init(); 只有在系统支持proc文件系统即配置了CONFIG_PROC_FS选项时才被调用。#endif check_bugs(); acpi_early_init(); /* before LAPIC and SMP init */ /* Do the rest non-__inited, were now alive */ rest_init(); 该函数创建init()内核进程即1号进程然后是系统启动进程即0号进程空闲。}    四、实验总结     当计算机电源启动BIOS代码被调用执行然后开始调用执行Linux内核初始化代码在平台相关的汇编代码 执行完毕后会跳转到start_kernel()函数开始真正的内核初始化其中init_task创建了0号进程即最终的idle进程 随后rest_init()函数创建了init进程即1号进程以及kthreadd进程即2号进程系统开始正式对外工作了。    转载于:https://www.cnblogs.com/qindingtao/p/5268143.html