【linux课程实验总结】

张开发
2026/4/18 3:56:38 15 分钟阅读

分享文章

【linux课程实验总结】
实验一反汇编一个简单的C程序vimmain.cintg(intx){returnx3;}intf(intx){returng(x);}intmain(void){returnf(8)1;}gcc-S-omain.s main.c-m32sed-i/[.]/dmain.svimmain.s实验二mykernel 实验指导操作系统是如何工作的cd~/LinuxKernel/linux-3.9.4rm-rfmykernel patch-p1../mykernel_for_linux3.9.4sc.patchmakeallnoconfigmakeqemu-kernelarch/x86/boot/bzImagecdmykernelvimmypcb.h#defineMAX_TASK_NUM4#defineKERNEL_STACK_SIZE1024*2structThread{unsignedlongip;unsignedlongsp;};typedefstructPCB{intpid;volatilelongstate;unsignedlongstack[KERNEL_STACK_SIZE];structThreadthread;unsignedlongtask_entry;structPCB*next;}tPCB;voidmy_schedule(void);vimmymain.c#includemypcb.h#includelinux/tty.htPCB task[MAX_TASK_NUM];tPCB*my_current_taskNULL;volatileintmy_need_sched0;voidmy_process(void);void__initmy_start_kernel(void){intpid0;inti;task[pid].pidpid;task[pid].state0;task[pid].task_entrytask[pid].thread.ip(unsignedlong)my_process;task[pid].thread.sp(unsignedlong)task[pid].stack[KERNEL_STACK_SIZE-1];task[pid].nexttask[pid];for(i1;iMAX_TASK_NUM;i){memcpy(task[i],task[0],sizeof(tPCB));task[i].pidi;task[i].state-1;task[i].thread.sp(unsignedlong)task[i].stack[KERNEL_STACK_SIZE-1];task[i].nexttask[i-1].next;task[i-1].nexttask[i];}pid0;my_current_tasktask[pid];asmvolatile(movl %1,%%esp\n\tpushl %1\n\tpushl %0\n\tret\n\tpopl %%ebp\n\t::c(task[pid].thread.ip),d(task[pid].thread.sp));}voidmy_process(void){inti0;while(1){i;if(i%100000000){printk(KERN_NOTICEthis is process %d -\n,my_current_task-pid);if(my_need_sched1){my_need_sched0;my_schedule();}printk(KERN_NOTICEthis is process %d \n,my_current_task-pid);}}}myinterrupt.c#includemypcb.h#includelinux/types.h#includelinux/string.h#includelinux/ctype.h#includelinux/tty.h#includelinux/vmalloc.hexterntPCB task[MAX_TASK_NUM];externtPCB*my_current_task;externvolatileintmy_need_sched;volatileinttime_count0;voidmy_timer_handler(void){if(time_count%10000my_need_sched!1){printk(KERN_NOTICEmy_timer_handler here\n);my_need_sched1;}time_count;return;}voidmy_schedule(void){tPCB*next;tPCB*prev;if(my_current_taskNULL||my_current_task-nextNULL){return;}printk(KERN_NOTICEmy_schedule\n);nextmy_current_task-next;prevmy_current_task;if(next-state0){my_current_tasknext;printk(KERN_NOTICEswitch %d to %d\n,prev-pid,next-pid);asmvolatile(pushl %%ebp\n\tmovl %%esp,%0\n\tmovl %2,%%esp\n\tmovl $1f,%1\n\tpushl %3\n\tret\n\t1:\tpopl %%ebp\n\t:m(prev-thread.sp),m(prev-thread.ip):m(next-thread.sp),m(next-thread.ip));}else{next-state0;my_current_tasknext;printk(KERN_NOTICEswitch %d to %d\n,prev-pid,next-pid);asmvolatile(pushl %%ebp\n\tmovl %%esp,%0\n\tmovl %2,%%esp\n\tmovl %2,%%ebp\n\tmovl $1f,%1\n\tpushl %3\n\tret\n\t1:\tpopl %%ebp\n\t:m(prev-thread.sp),m(prev-thread.ip):m(next-thread.sp),m(next-thread.ip));}return;}lscd~/LinuxKernel/linux-3.9.4makeqemu-kernelarch/x86/boot/bzImage实验三跟踪分析 Linux 内核的启动过程cd~/LinuxKernel/ qemu-kernellinux-3.18.6/arch/x86/boot/bzImage-initrdrootfs.imgcd~/LinuxKernel/ qemu-kernellinux-3.18.6/arch/x86/boot/bzImage-initrdrootfs.img-s-S另开一个shell窗口gdbfilelinux-3.18.6/vmlinux target remote:1234breakstart_kernel c listbreakrest_init c listbreakkernel_init c list实验四使用库函数 API 和 C 代码中嵌入汇编代码两种方式使用同一个系统调用选择了getpid和getppid系统调用来实现直接调用库函数API。vimtest4_1.c#includestdio.h#includeunistd.hintmain(){printf(PID: %d\n,getpid());printf(PPID: %d\n,getppid());return0;}gcc test4_1.c-otest4_1 ./test4_1vimtest4_2.c#includestdio.h#includesys/types.h#includeunistd.hintmain(){pid_tpid,ppid;asmvolatile(mov $0x14, %%eax\n\tint $0x80\n\tmov %%eax, %0\n\t:r(pid)::%eax);asmvolatile(mov $0x40, %%eax\n\tint $0x80\n\tmov %%eax, %0\n\t:r(ppid)::%eax);printf(PID: %d\n,pid);printf(PPID: %d\n,ppid);return0;}gcc test4_2.c-otest4_2 ./test4_2实验五分析 system_call 中断处理过程cd~/LinuxKernelrm-rfmenugitclone https://github.com/mengning/menu.gitcdmenuvimtest.cint_20252804_main1(){pid_tpidgetpid();pid_tppidgetppid();printf(pid%d ppid%d\n,pid,ppid);}int_20252804_main2(){pid_tpid,ppid;asmvolatile(mov $0x14, %%eax\n\t// getpid 的ID为20int $0x80\n\tmov %%eax, %0\n\t:r(pid)::%eax);asmvolatile(mov $0x40, %%eax\n\t// getppid 的ID为64int $0x80\n\tmov %%eax, %0\n\t:r(ppid)::%eax);printf(pid%d ppid%d\n,pid,ppid);return0;}MenuConfig(getpid1,system_call_1,_20252804_main1);MenuConfig(getpid_asm_2,system_call_asm_2,_20252804_main2);makerootfscd~/LinuxKernel qemu-kernellinux-3.18.6/arch/x86/boot/bzImage-initrdrootfs.img-s-S新开一个shellcd~/LinuxKernel gdbfilelinux-3.18.6/vmlinux target remote:1234 b sys_getpid cQEMU里面输入getpid1 getpid_asm_2实验六分析 Linux 内核创建一个新进程的过程cd~/LinuxKernelrmmenu-rfgitclone https://github.com/mengning/menu.gitcdmenumvtest_fork.c test.cmakerootfscd~/LinuxKernel qemu-kernellinux-3.18.6/arch/x86/boot/bzImage-initrdrootfs.img-s-S新开一个shellcd~/LinuxKernel gdb file linux-3.18.6/vmlinux target remote:1234b sys_clone b do_fork b dup_task_struct b copy_process b copy_thread b ret_from_fork c c c c c c在 Linux 内核里fork 函数作为创建新进程的系统调用其核心逻辑是通过复制当前父进程的状态生成子进程。这一系统调用的处理流程涉及多个内核函数其中 do_fork 承担着核心职责它负责子进程的创建与初始化工作并会调用 copy_process 函数来复制父进程的关键数据结构——像文件描述符表、内存映射关系、信号处理程序等都在复制范围内。此外copy_thread 函数也扮演着重要角色它的作用是复制内核堆栈内容从而保证新进程能拥有独立的内核堆栈确保父子进程在 kernel 态运行时的栈空间相互隔离实验七Linux 内核如何装载和启动一个可执行程序cd~/LinuxKernelvimtest.c#includestdio.hintmain(){printf(my StudentId is 20252804\n);return0;}gcc-otesttest.c ./test readelf-htestcdmkdirtestcdtestvimmyecho.c#includestdio.h#includeunistd.h#includestdlib.hintmain(intargc,char*argv[]){for(inti0;iargc;i){printf(argv[%d]:%s\n,i,argv[i]);}exit(EXIT_SUCCESS);}vimmyexecve.c#includestdio.h#includestdlib.h#includeunistd.hintmain(intargc,char*argv[]){char*list1[]{NULL,Hello,Linux,World,NULL};char*list2[]{NULL};if(argc!2){fprintf(stderr,%s wrong,argv[0]);exit(EXIT_FAILURE);}list1[0]argv[1];execve(argv[1],list1,list2);perror(execve);}gcc-stdc99-omyecho.c myecho gcc-stdc99-omyexecve.c myexecve ./myexecve ./myechovimshared_lib.c#includestdio.hvoidmy_function(){printf(excute success\n);}vimmain_exec_link_time.c#includestdio.hexternvoidmy_function();intmain(){printf(This method is loading\n);my_function();return0;}vimmain_run_time.c#includestdio.h#includedlfcn.hintmain(){void*handle;void(*my_function)();handledlopen(shared_lib.so,RTLD_LAZY);if(!handle){fprintf(stderr,%s\n,dlerror());return1;}printf(The method is running\n);my_functiondlsym(handle,my_function);my_function();dlclose(handle);return0;}gcc-shared-oshared_lib.so-fPICshared_lib.ccpshared_lib.so libshared_lib.soexportLD_LIBRARY_PATH$PWDgcc main_exec_link_time.c-oexec_link_time -L.-lshared_lib./exec_link_time gcc main_run_time.c-orun_time-ldl./run_timecd~/LinuxKernelrmmenu-rfgitclone https://github.com/mengning/menu.gitcdmenumvtest_exec.c test.cmakerootfscd~/LinuxKernel qemu-kernellinux-3.18.6/arch/x86/boot/bzImage-initrdrootfs.img-s-S新开一个shellcd~/LinuxKernel gdbfilelinux-3.18.6/vmlinux target remote:1234 b sys_execve b load_elf_binary b start_thread c c cQEMU里面输入helpexec实验八理解进程调度时机跟踪分析进程调度与进程切换的过程cd~/LinuxKernelgrep-rschedule()/home/shiyanlou/LinuxKernel/linux-3.9.4/kernelcd~/LinuxKernelrm-rfmenugitclone https://github.com/mengning/menu.gitcdmenumvtest_exec.c test.cmakerootfscd~/LinuxKernel qemu-kernellinux-3.18.6/arch/x86/boot/bzImage-initrdrootfs.img-s-S另开一个shellcd~/LinuxKernel gdbfilelinux-3.18.6/vmlinux target remote:1234 b schedule b context_switch b pick_next_task c c c

更多文章