logo资料库

重庆大学计算机学院linux实验报告1.doc

第1页 / 共19页
第2页 / 共19页
第3页 / 共19页
第4页 / 共19页
第5页 / 共19页
第6页 / 共19页
第7页 / 共19页
第8页 / 共19页
资料共19页,剩余部分请下载后查看
《linux 操作系统》实验报告 年级、专业、班级 姓名 实验题目 Linux 内核编译与系统调用 实验时间 2014/4/16 实验地点 A 区主教学楼 0414 实验成绩 教师评价: 实验性质 □验证性 □设计性 □综合性 □算法/实验过程正确; □源程序/实验内容提交 □程序结构/实验步骤合理; □实验结果正确; □语法、语义正确; □报告规范; 其他: 评价教师签名: 一、实验目的 (1)掌握 linux 内核编译过程 (2)掌握 fork()和 clone()创建进程 二、实验项目内容 1)Linux 内核编译; 2) 分别用 fork()和 clone()创建进程:列出子进程和父进程的进程号、进 程名和进程状态等信息; 三、实验过程或算法(源程序) 编译内核: 为何要重新编译内核? Linux 作为一个自由软件,在广大爱好者的支持下,内核版本不断更新。新的内 核修订了旧内核的 bug,并增加了许多新的特性。如果用户想要使用这些新特性,或 想根据自己的系统度身定制一个更高效,更稳定的内核,就需要重新编译 Linux 内核。 通常,更新的内核会支持更多的硬件,具备更好的进程管理能力,运行速度更快、 更稳定,并且一般会修复老版本中发现的许多漏洞等,经常性地选择升级更新的系统 内核是 Linux 使用者的必要操作内容。 一、打开虚拟机, power on Ubuntu。 二、在登陆界面输入密码:123456 三、将 linux-3.4.38.tar.xz 包移动到“主文件夹”目录下 报告创建时间:
四、打开命令终端:ctrl+alt+t; 查看当前内核版本号:$ uname -a 获取 root 权限: $ sudo su 提示输入密码:123456 五、解压源代码包: # xz –d linux-3.4.38.tar.xz # tar xvf linux-3.4.38.tar /usr/src/linux-3.4.38 六、编译内核喽 (一)清除当前目录下残留的.config 和.o 文件 在终端中进入刚刚的这个/usr/src/linux-3.4.38 文件夹,输入命令: $ make mrproper 当然我们这里是第一次编译这个内核,所以不存在清理不清理,如果以后需要对这个 内核重新编译,这一步骤当然是十分必要的啦。 (二)安装 ncurses 作为操作系统的内核,其内容和功能必然非常繁杂,包括处理器调度,内存管理, 文件系统管理,进程通讯以及设备管理等等,而对于不同的硬件,其配置选项也不相 同,所以在编译源代码之前必须设置编译选项。其实我觉得这一步是升级内核整个过 程中最有技术含量的,因为要根据自己的需要正确选择 yes or no 需要对计算机方方 面面的知识都有所了解。但是这里的选项实在是太多了,大概有几百项之多,我以前 曾尝试着一项一项的选,但是最后还是放弃了,因为有很多选项不是很明白。 既然这样,难道没有什么简便的方法么?当然有!那就是 make menuconfig 或者 make xconfig。我使用的是 make menuconfig,但是前提条件是要装 ncurses。 对于下载好的这个 ncurses 包,我们把它放到/usr/local 下面;接着终端进入这个文件 夹:$ cd /usr/local。 解压缩并且释放文件包:$ tar zxvfncurses.tar.gz 按照你的系统环境制作安装配置文件:$ ./configure 编译源代码并且编译 NCURSES 库:$ make 切换到 root 用户环境: $ make install 这样我们的 ncurses 库就已经编译完成了。 (三)配置内核编译选项 在 make menuconfig 过程中也会有一些选项需要你来设置*, y, n 或者 m,选择* 表示选项中的内容被直接编入内核中,选择 m 表示选项中的内容编入内核,而只是 编成独立的 module,用到时才调用。 在当前文件路径下,输入命令: makemenuconfig 这里就出现了一个配置选项的图形化界面,因为我们是用的虚拟机,所以一定要 选择把 SCSI 设备编译进去。最后保存为.config 文件并退出。 (四)编译内核 这步是时间最长的一个步骤,一般在 3 个小时左右。 编译内核只需在终端输入 make,然后等待编译的完成。 (五)编译和安装内核模块 输入 make modules_install,这步很快能完成。 (六)安装内核 输入 make install
(七)生成启动 依次输入: sudomkinitramfs -o /boot/initrd.img-2.6.36 sudo update-initramfs -c -k 2.6.36 sudo update-grub2 //自动修改系统引导配置,产生 grub.cfg 启动文件。 用 fork() 和 clone()分别创建进程,并列出子进程和父进程的进程号、进程名和进程 状态。 Fork(): 一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创 建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如 果初始参数或者传入的变量不同,两个进程也可以做不同的事。 fork()创建一个子进程,即 intpid = fork(), fork()进入内核,调用一次返回两次, 如果返回的 pid == 0 子进程先返回,如果 pid> 0(此时返回的是子进程的 pid),父进 程先返回。至于子进程和父进程哪个先返回,要看内核的调度算法。输出次序乱序, 都有可能。父进程和子进程是并发执行的。返回指的是这个函数 return pid;这个语句 被执行了两次。 因为创建了一个子进程后,那么子进程中的 fork 也要返回一次。 在 Linux 下如果内存没有被写的话,那么父子进程是共用内存空间的,所以内存 中的同一个 fork 函数会在两个进程中调用到。在父进程中返回的就是子进程 id,子 进程中返回的是 0. Clone(): 我们这里主要用带参数的 clone()函数来创建“轻量级的进程”—线程。线程的创 建和普通进程的创建类似,只不过在调用 clone()的时候需要传递一些参数标志来指 明需要共享的资源: int clone(int (*fn)(void *), void *child_stack, int flags, void *arg); 这里 fn 是函数指针,我们知道进程的 4 要素,这个就是指向程序的指针,就是 所谓的“剧本", child_stack 明显是为子进程分配系统堆栈空间(在 linux 下系统堆栈空 间是 2 页面,就是 8K 的内存,其中在这块内存中,低地址上放入了值,这个值就是 进程控制块 task_struct 的值),flags 就是标志用来描述你需要从父进程继承那些资源, arg 就是传给子进程的参数)。下面是 flags 可以取的值 CLONE_PARENT 创建的子进程的父进程是调用者的父进程,新进程与创建 它的进程成了“兄弟”而不是“父子” CLONE_FS 目录、umask 子进程与父进程共享相同的文件系统,包括 root、当前 CLONE_FILES 子进程与父进程共享相同的文件描述符(file descriptor) CLONE_NEWNS 在新的 namespace 启动子进程,namespace 描述了进程的文 表 件 hierarchy CLONE_SIGHAND 子进程与父进程共享相同的信号处理(signal handler)表 CLONE_PTRACE 若父进程被 trace,子进程也被 trace CLONE_VFORK CLONE_VM CLONE_PID 子进程与父进程运行于相同的内存空间 子进程在创建时 PID 与父进程一致 父进程被挂起,直至子进程释放虚拟内存资源
CLONE_THREAD Linux 2.4 中增加以支持 POSIX 线程标准,子进程与父进 程共享相同的线程群 fork.c #include #include void main() { intpid; pid = fork(); if(pid == -1) printf(“Erro!\n”); else if(pid == 0) printf(“childprocess is running, parentpid is %d, childpid is %d.\n ”, getpid(), pid); else printf(“parentprocess is running, parentpid is %d, childpid is %d.\n ”, getpid(), pid”); } clone.c #include #include #include #include #define FIBER_STACK 7900 void *stack; int do_something() { printf("childthread is running, the pid is: %d\n", getpid()); free(stack); sleep(5); printf("childthread exits!!!\n"); exit(0); } int main() { stack = malloc(FIBER_STACK); if(!stack) printf("failed in creating thread!!!\n"); exit(0); { } printf("creating childthread!!!\n"); clone(&do_something, (char *)stack+FIBER_STACK, CLONE_VM|CLONE_VFORK, 0); printf("parentthread is running, the pid is: %d\n", getpid()); exit(1); } (注意:在编译时要用到 gcc 的-D_GNU_SOURCE 选项)
四、实验结果及分析和(或)源程序调试过程 (一)内核编译 1 查询原 linux 内核版本
2 解压源代码包
3 清除当前目录下残留的.config 和.o 文件
4 安装 ncurses 4.1 解压 ncurses
分享到:
收藏