linux实验_添加系统调用-完整版
- 格式:doc
- 大小:145.50 KB
- 文档页数:5
一、题目:新增Linux系统调用(1)需要重新编译Linux内核(2)增加一个Linux的系统调用(3)写一个用户程序进行调用测试。
系统调用实现的功能:计算一个数字的三次方,并打印出来。
二、版本:编译版本:Win10上虚拟机(Virtual Box) Ubuntu(64bit)15.04系统原内核版本:3.19.0编译的新内核源码版本:3.2.75不同内核版本,32位和64位文件位置以及文件名可能有所不同。
添加系统调用时要根据自己的版本的文件位置和文件名修改相应的三个文件。
三、步骤:1.前期准备:下载内核及解压1.1下载内核:1.2打开终端获得权限然后再输入su输入刚刚设置的密码。
1.3移动文件并解压下载目录2.添加系统调用2.1添加系统调用函数在文末添加调用函数。
然后保存,关闭。
2.2 添加调用函数声明在文末#endif前添加函数声明。
然后保存关闭。
2.3添加系统调用号因为前一个系统调用号是311 所以这里我们写312将原本的#defineNR_syscalls (__NR_syscall_max+1)修改为:#defineNR_syscalls (__NR_syscall_max + 2)然后保存,关闭。
3.编译内核3.1安装基本编译器套件3.2编译3.1make mrproper清除以前配置(如果是第一次编译,不用执行此操作)3.2 make menuconfig配置内核(此处选择了默认配置)3.3 make编译内核如果电脑是双核则也可以用make–j4代替make(双核编译会更快一些)接下来就是漫长的等待过程,不过要随时注意是否编译过程中因有错误而停止。
我的电脑用了两个小时。
(也有教程里用的是make bzlmage和makemodules,make bzlmage+make modules=make)4.安装内核4.1makemodules_install4.2makeinstall4.2 reboot重启(或不使用命令直接对电脑进行重启)ﻩ重启之后在开机时候开机时候,如果是虚拟机需要同时按esc和↑键出现开机启动项(如果是真机开机一般会自动出现开机启动项),选择新建的内核版本进入。
一、构建基本的实验环境1.1基本实验环境与前提条件Windows7 、Word 2010、Vmware WorkStation 8.5、AdobeReaderReadHatLinux 9.0,gcc,viLinux内核[V2.4.18]1.2虚拟机的安装及使用1.3将Linux 内核源代码及配置文件传送给虚拟机上的Red Hat Linux V9.0 系统配置网络时遇到这个问题,Determining IP information for eth0... failed; no link present. Check cable?通过查找资料发现是系统的Bug,解决方法如下:到/etc/sysconfig/network-scripts/ifcfg-eth0在文件最后一行中加入check_link_down () {return 1;}另外如果存在/etc/sysconfig/networking/profiles/default/ifcfg-eth0 文件,则同样在其中加入这一段东西即可,然后重启系统。
设置网络为DHCP,重新启动就可以,啦,直接上图最后将内核代码下载到/root目录下二、Linux 内核编译、配置与调试2.1 内核配置与编译2.1.1、解压内核源代码文件tar -zxf linux-2.4.18.tar.gz2.1.2、解压后如下2.1.3、拷贝linux,命名为linux-2.4.18cp -r linux linux-2.4.182.1.4、移动config-2.4.18forMP.txt到linux-2.4.18根目录,替换掉.config2.1.5、进入linux-2.4.18目录,配置和编译内核模块make oldconfigmake depmake cleanmake bzImagemake modules2.2 内核安装与测试2.2.1安装内核映像文件cp arch/i386/boot/bzImage /boot/vmlinux-2.4.182.2.2拷贝和安装Linux系统映射文件System.map,并创建其与系统映射文件System.map之间的符号链接2.2.3执行命令make modules_install 以安装可动态加载的内核模块2.2.4添加启动项的配置利用vi编辑器,vi grub.conf查看/ 所在的位置,为/dev/sda32.2.5reboot重新启动系统,从自己创建的内核启动系统启动后查看内核分别用uname –r,和dmesg查看三、Linux 系统调用添加与实现3.1 在内核增加系统调用3.1.1结构体struct srz_rusage可声明如下:.struct srz_rusage {struct timeval ru_utime; /* user time used */struct timeval ru_stime; /* system time used */long ru_majflt; /* major page faults */long ru_minflt; /* minor page faults */long ru_nswap; /* swaps */};3.1.2添加到linux-2.4.18/include/linux下的resource.h中3.1.3添加的系统调用名称为:int get_process_usage(pid_t, struct srz_rusage*);参考的getrusage和sys_getrusage的代码在linux-2.4.18/linux/kernel/sys.c下面3.1.4分析getrusage()和sys_getrusage()的源代码1)数据结构rusage 在头文件resource.h中定义。
操作系统实验一向LINUX内核增加一个系统调用一、背景介绍操作系统是计算机硬件与应用程序之间的接口,负责管理和调度计算机系统的各种资源,并提供用户与计算机系统的交互界面。
内核是操作系统的核心部分,负责管理和分配计算机系统的资源,执行各种任务。
系统调用是操作系统提供给应用程序的一种接口,可以让应用程序访问内核提供的功能,例如文件操作、进程管理、网络通信等。
在一些情况下,我们可能需要在LINUX内核中增加新的系统调用,以满足特定的需求。
本文将介绍如何向LINUX内核增加一个系统调用的具体步骤。
二、增加系统调用的步骤1.编写系统调用的具体实现代码首先,我们需要编写一个具体的系统调用的实现代码。
在LINUX内核中,系统调用的实现代码通常位于内核的/syscalls目录下。
我们可以在该目录下新建一个.c文件,编写我们自己的系统调用代码。
2.修改内核源代码3.更新系统调用表每个系统调用都在内核中有一个唯一的标识符,存储在一个叫做系统调用表的地方。
我们需要更新系统调用表,将新增的系统调用添加到表中。
这样,用户程序才能够通过系统调用号来调用新增的系统调用。
4.重新编译内核在修改完内核源代码后,我们需要重新编译内核。
这通常涉及到一些繁琐的步骤,例如配置内核选项、编译内核、安装内核等。
在重新编译内核之后,我们需要重新启动计算机,使新的内核生效。
5.修改用户程序最后,我们需要修改用户程序,以便能够调用新增的系统调用。
用户程序通常是通过C语言编写的,我们可以在用户程序的代码中添加对新增系统调用的调用代码。
三、实验结果在完成上述步骤后,我们就成功地向LINUX内核增加了一个系统调用。
用户程序可以通过系统调用调用自己新增的系统调用,从而实现特定的功能。
总结:本文介绍了向LINUX内核增加一个系统调用的具体步骤,包括编写系统调用的具体实现代码、修改内核源代码、更新系统调用表、重新编译内核和修改用户程序。
在实施这些步骤之前,我们需要对操作系统和内核的相关概念有一定的了解,并具备一定的编程能力。
第1篇一、实验目的1. 了解系统调用的基本概念和作用。
2. 掌握在Linux内核中增加系统调用的方法。
3. 熟悉系统调用在用户空间和内核空间之间的交互过程。
4. 提高编程能力和系统理解能力。
二、实验环境1. 操作系统:Linux2. 编译器:gcc3. 开发工具:内核源代码、makefile三、实验原理系统调用是操作系统提供的一种服务,允许用户空间程序请求内核空间的服务。
在Linux内核中,系统调用通过系统调用表来实现。
增加系统调用需要修改内核源代码,并重新编译内核。
四、实验步骤1. 创建系统调用函数首先,我们需要创建一个系统调用函数,该函数将实现一个简单的功能,例如打印一条消息。
以下是一个简单的系统调用函数示例:```cinclude <linux/module.h>include <linux/kernel.h>include <linux/init.h>static int __init hello_init(void) {printk(KERN_INFO "Hello, World!\n");return 0;}static void __exit hello_exit(void) {printk(KERN_INFO "Goodbye, World!\n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Your Name");MODULE_DESCRIPTION("A simple system call module");MODULE_VERSION("0.1");```2. 修改系统调用表接下来,我们需要修改内核源代码中的系统调用表,以注册我们创建的系统调用。
选题要求:在Linux内核中增加一个系统调用,并编写对应的linux应用程序。
利用该系统调用能够遍历系统当前所有进程的任务描述符,并按进程父子关系将这些描述符所对应的进程id(PID)组织成树形结构显示。
目录一.程序的主要设计思路,实现方式 (1)1.1 添加系统调用的两种方法 (1)1.1.1编译内核法 (1)1.1.2内核模块法 (1)1.2 程序的主要设计思路 (1)1.3 环境 (2)二.程序的模块划分,及对每个模块的说明 (2)2.1 通过内核模块实现添加系统调用 (2)2.1.1修改系统调用的模块 (2)2.1.2获取sys_call_table的地址 (2)2.1.3清除内存区域的写保护 (3)2.2 编写系统调用指定自己的系统调用 (4)2.2.1内核的初始化函数 (4)2.2.2自己的系统调用服务例程 (4)2.2.3移除内核模块时,将原有的系统调用进行还原 (6)2.2.4模块注册相关 (6)2.3 编写用户态的测试程序 (6)2.4 编写Makefile文件 (7)三.所遇到的问题及解决的方法 (8)3.1 进程个数确定 (8)3.2 被更改的系统调用号的选择 (8)3.3 获取系统调用表的地址 (8)3.4 内核和用户态数据交换 (8)四.程序运行结果及使用说明 (8)4.1 将编译出来的内核模块hello.ko加载到内核中 (8)4.2通过dmesg查看输出信息是否正确 (9)4.3运行测试程序,输出树状打印结果(部分结果截图) (9)4.4卸载自定义模块 (10)五.附录 (11)5.1 内核模块程序hello.c (11)5.2 测试程序hello_test.c (14)5.3 Makefile文件 (14)一.程序的主要设计思路,实现方式1.1 添加系统调用的两种方法1.1.1编译内核法编写好源码之后以上准备工作做完之后,然后就要进行编译内核了,以下是编译内核的一个过程1.1.2内核模块法内核模块可以作为独立程序来编译的函数和数据类型的集合。
实验3:添加系统调用long get_cputime(pid_t pid);get_cputime返回由pid指定的进程占用CPU的总时间。
实验步骤:1)在arch/i386/kernel/entry.S文件中的系统调用入口表中,找到某个空项:.long SYMBOL_NAME(sys_ni_syscall)修改为新加系统调用的入口项:.long SYMBOL_NAME(sys_get_cputime) /* 254——系统调用号*/记住系统调用号(在系统调用入口表中的第几个入口),例如254。
2)在核心文件kernel/sys.c中添加实现系统调用get_cputime()的代码段:asmlinkage long sys_get_cputime(pid_t pid){······}使用核心函数find_task_by_pid(pid)获得pid的PCB数据结构(task_struct)指针p;进程占用CPU的总时间=p->times.tms_utime + p->times.tms_stime3)生成和运行新内核make bzImagemake installreboot——选择新内核运行4)在/usr/include/asm/unistd.h文件中增加:#define __NR_get_cputime 2545)编写c程序使用新的系统调用#include<stdio.h>#include<errno.h>#include <sys/types.h>#include<linux/unistd.h>_syscall1(long, get_cputime, pid_t, p)int main(){····ct=get_cputime(pid);printf("The total used cputime is %ld\n", ct);····}。
实验辅助三:添加系统调用Saturday,OS_TANovember22,20091Contents1文档定位32运行环境3 3准备工作3 4实验说明35操作步骤45.1明确步骤 (4)5.2修改代码 (4)5.2.1修改用户空间unistd_32.h代码 (5)5.2.2修改内核空间unistd_32.h代码 (5)5.2.3修改内核syscall_table_32.S代码 (6)5.2.4修改内核sys.c代码 (7)5.3编译内核 (8)5.4编写用户态程序 (8)6结束语91文档定位实验辅助主要的作用是以TA自己的经验来辅助同学们做实验,让大家少走弯路,少在Linux繁杂的内核版本和发行版本的中浪费时间,而把主要的精力集中在理解和实践操作系统本身。
有关原理性的东西,在实验说明文档中已有详细的介绍。
如果大家有关原理性的问题,请参考实验说明文档。
在实验辅助文档中,我们主要讲实验步骤,帮助大家理解实验步骤,而不触及原理性的东西。
TA所选的发行版是当前最流行的Ubuntu9.04。
编译所有的内核代码是2.6.26(注意,这个要与2.6.26.1,2.6.26.2,等版本相区别。
)另外,这个文档也不是一份很严肃的文档。
Take It Easy∼同时,也难免会有这样或者那样的问题,欢迎大家指正。
请联系:Saturday2运行环境操作系统:Ubuntu9.04内核版本:2.6.26虚拟机:Sun VirtualBox3.0.4(注意不是开源版本的VirtualBox-OSE)主系统:Fedora11以上运行环境中最重要的是操作系统和内核版本,这两个一定要与实验辅助中保持一致。
3准备工作完全阅读了《实验辅助二:编译Linux内核》,并已经完成了实验二。
4实验说明用大家最简单的话来说,实验三就是实验二的升级版。
实验二编译的源代码是直接从官网上下载的。
而实验三就是要修改官网上下载的源代码,然后再重新编译内核,最后在用户空间写一个程序来验证,我们对于内核代码的修改工作做得是否这样正确的。
操作系统《实验2》实验报告实验项目2:增加新的系统调用学号1209050123 姓名宋玉美课程号实验地点指导教师万少华时间2013.11评语:成绩教师签字万少华线性表链式存储(双向链表)插入、删除运算1、预备知识:Linux内核结构、Linux内核源码、Linux系统调用2、实验目的:增加新的系统调用3、实验内容及要求:(1)增加新的系统调用新增的系统调用名为get_proc_run_time,其功能是根据指定的进程pid,从该进程的进程描述符task_struct结构中提取出它的系统时间stime与用户时间utime (2)编译内核用编译内核的方法,将其增加到内核源码并编译内核(3)程序测试在用户空间编写测试程序测试该系统调用。
程序中调用此系统调用能准确的度量一个程序的时间效率,考虑是否还有别的方法比这更准确的学生信息,参数x, i,j从键盘输入(4)给出程序运行截图。
4、该文档的文件名不要修改,存入<学号><姓名> 命名的文件夹中5、该表中的数据只需填空,已有内容不要修改1.添加系统调用函数,修改文件/usr/src/linux—3.5/kernel/sys.c2. 添加系统调用号,修改文件/arch/x86/systemcalls/syscall_32.tbl3. 添加声明到头文件,修改文件,/include/linux/syscalls.h4. 重新编译内核(前几步只顾着运行忘记截图了,不好意思哈老师~)1)安装ncurses2)make menuconfig3)make dep 确定依赖性4)make clean 清理编译中间文件5)make bzImage 生成新内核6)make modules 生成modules 7)安装modules9)安装内核make install 10)配置grub引导程序13)重启。
重启系统,从grub菜单中选中新内核引导linux。
中国地质大学(武汉)《操作系统原理》课程实验报告数据科学与大数据技术专业班级195182学生姓名钟欢任课教师康晓军完成时间2020年3月31日实验一——实现一个linux的系统调用一、实验目的1.加深对系统调用的理解,掌握增加与调用系统调用的方法。
2.掌握内核编译方法。
二、实验思路1.增加新的系统调用:新增的系统调用名为Hello,其功能是打印输出“This is ZhongHuan ’ s system call ! wo zhong yu cheng gong le !”2.编译内核:用编译内核的方法,将其增加进内核源码并编译内核。
3.测试:在用户控件编写测试程序测试该系统调用。
三、实验步骤1.系统调用的添加在Linux中添加新的系统调用,需执行多个步骤才能添加成功:(1)第一步完成系统调用函数在内核源码目录kernel/sys.c文件中编写待添加的系统调用函数。
该函数的名称应该是新的系统调用名称前面加上sys_标志。
新加的系统调用为hello(void),在kernel/sys.c文件中添加源代码:asmlinkage long sys_hello(void){printk("This is ZhongHuan's system call! wo zhong yu cheng gong le!");return 1;}(2)第二步在系统函数表中表项添加新的系统调用后,需要让Linux内核的其余部分知晓该程序的存在。
在内核源码目录arch/x86/entry/syscalls下修改文件syscall_64.tbl。
该文件用来对sys_call_table[]数组实行原始化,数组包含指向内核中每个系统调用的指针。
在该文件中的最后一行添加自己的系统调用表项:335 64 hello sys_hello(),这样就在数组中添加了新的内核函数指针。
(3)第三步添加系统调用号在内核源码目录arch/x86/include/asm下修改头文件unistd_32.h。
LinuxOS实验⼀:内核编译及添加系统调⽤简单整理下上周做的OS的lab1,前半部分主要介绍Linux内核编译和添加系统调⽤的流程,后半部分主要简要探索⼀下添加的系统调⽤中所⽤到的内核函数的源码。
⾸先贴⼀下这次实验的要求和我的实验流程图:Linux内核编译流程实验环境我的实验环境是VMware虚拟机下的Ubuntu 16.04,使⽤uname -a命令查看了⾃⼰的内核版本是4.15.0,于是确定待编译的新内核版本是:4.16.1(这个版本应略⾼于Linux系统的内核版本)。
同时,由于在内核编译过程中会⽣成较多的临时⽂件,如果磁盘空间预留很⼩,会出现磁盘空间不⾜的错误⽽导致内核编译失败;内存太⼩则会影响编译速度。
所以,这⾥建议虚拟机的配置参数:内存2GB以上,磁盘空间40GB以上。
由于我在做内核编译之前的时候就已经安装了linux虚拟机,所以这⾥我需要先扩展磁盘内存,具体参考了以下博⽂:。
下载内核源码并解压在中找到对应版本的内核源码并下载(如上⽂所说,这⾥我选择4.16.10,请视Linux系统的具体情况⽽定):在Linux系统中切换⾄root⽤户(随后的所有步骤都应以root⽤户进⾏操作,⽆法切换的可以尝试passwd命令修改root⽤户密码),然后将压缩⽂件复制到/home或其他⽐较空闲的⽬录中,进⼊压缩⽂件所在⼦⽬录,使⽤以下命令解压:xz -d linux-4.16.10.tar.xztar -xvf linux-4.16.10.tar清楚残留的.config和.o⽂件每次完全重新编译的时候都应从这⼀步开始,为了防⽌出现错误,我们先安装所需要的对应包:apt-get install libncurses5-dev随后执⾏命令:make mrproper配置内核执⾏命令:make menuconfig,随后出现诸如以下界⾯:我们选择默认值:保存配置信息,选⽤默认的⽂件名.config,最后编译内核先安装所需的包以防编译时报错:=>安装openssl:apt-get install libssl-dev=>安装bison:apt-get install bison=>安装flex:apt-get install flex随后执⾏命令:make,强烈建议使⽤命令make -j4或make -j8来加快编译速度,这⾥第⼀次进⾏内核编译的时候需要⽐较长的时间,我的电脑⼤概跑了⼀个多⼩时。
1、下载内核apt-get install linux-source在/usr/src下2、解压内核cd /usr/srctar -jxvf linux-source-2.6.35.tar.bz2将内核解压到/usr/src3、修改文件a)/usr/src/linux-source-2.6.35/kernel/sys.c 可以用右键管理员打开或者gedit /usr/src/linux-source-2.6.35/kernel/sys.c 在文件最后添加asmlinkage int sys_mycall(int number){printk("这是我添加的第一个系统调用"); return number;}asmlinkage int sys_addtotal(int number){int i=0,enddate=0;printk("这是我添加的第二个系统调用"); while(i<=number)enddate+=i++;return enddate;}asmlinkage int sys_three(){printk("这是我添加的第三个系统调用");return 0;}b)/usr/src/linux-source-2.6.35/arch/x86/kernel/syscall_table_32.S 可以用右键管理员打开或者gedit /usr/src/linux-source-2.6.35/arch/x86/kernel/syscall_table_32.S 然后在一列 .long sys_XXXX的下一行添加.long sys_mycall.long sys_addtotal.long sys_three并记住他们分别是第几个.long sys_XXXXc)/usr/src/linux-source-2.6.35/arch/x86/include/asm/unistd_32.h可以用右键管理员打开或者gedit /usr/src/linux-source-2.6.35/arch/x86/include/asm/unistd_32.h 在一列#define __NR_XXXX NNN后添加几行#define __NR_mycall 338#define __NR_addtotal 339#define __NR_three 340注意后面那个数字是接着上面那几行下来的d)/usr/src/linux-source-2.6.35/ubuntu/omnibook/Makefile如果在后面编译模块时出现ld: /ubuntu/omnibook/sections.lds: No such file: No such file or directorymake[2]: *** [ubuntu/omnibook/omnibook.o] Error 1make[1]: *** [ubuntu/omnibook] Error 2make: *** [ubuntu] Error 2以上错误,则需要修改,不过我建议还是先改了再说可以用右键管理员打开或者gedit /usr/src/linux-source-2.6.35/ubuntu/omnibook/Makefile找到下面两行#EXTRA_LDFLAGS += $(src)/sections.ldsEXTRA_LDFLAGS += $(PWD)/ubuntu/omnibook/sections.lds调换一下‘#’的位置,如下EXTRA_LDFLAGS += $(src)/sections.lds#EXTRA_LDFLAGS += $(PWD)/ubuntu/omnibook/sections.lds4、编译内核进入解压目录cd /usr/src/linux-source-2.6.35a)make mrproper //清除内核中不稳定的目标文件,附属文件及内核配置文件b)make clean //清除以前生成的目标文件和其他文件c)make oldconfig// 采用默认的内核配置,如果这里出现选项,选择默认的选项,就是方括号内的第一个字母,不过我这里没出现选项d)make bzImage //编译内核,大概需要半小时e)make modules //编译模块,大概需要两小时,如果出现错误,看看是不是因为上面的第3步的d)没做f)make modules_install// 安装模块,比较快5、复制内核首先查看一下编译好的内核版本,以便命名打开/lib/modules里面应该多了一个纯数字不带"generic"的文件夹,那就是新内核版本号,我的是2.6.35.11然后复制内核cp /usr/src/linux-source-x.x.x/arch/i386/boot/bzImage /boot/vmlinuz-x.x.x-mykernel 6、创建initrd文件在创建之前先安装必要的程序apt-get install bootcd-mkinitramfsmkinitramfs -o /boot/initrd.img-x.x.x耐心等待创建完成7、更新配置GRUB引导列表可以用右键管理员打开/boot/grub/grub.cfg或者gedit /boot/grub/grub.cfg找到下面这种结构menuentry 'Ubuntu, with Linux 2.6.35-27-generic' --class ubuntu --class gnu-linux--class gnu --class os {recordfailinsmod part_msdosinsmod ext2set root='(hd1,msdos1)'search --no-floppy --fs-uuid --set 71a50d19-caef-4dff-9a7a-57cb1bbfe0c2linux /boot/vmlinuz-2.6.35-27-genericroot=UUID=71a50d19-caef-4dff-9a7a-57cb1bbfe0c2 ro quiet splashinitrd /boot/initrd.img-2.6.35-27-generic}menuentry 'Ubuntu, with Linux 2.6.35-27-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os {recordfailinsmod part_msdosinsmod ext2set root='(hd1,msdos1)'search --no-floppy --fs-uuid --set 71a50d19-caef-4dff-9a7a-57cb1bbfe0c2echo 'Loading Linux 2.6.35-27-generic ...'linux /boot/vmlinuz-2.6.35-27-genericroot=UUID=71a50d19-caef-4dff-9a7a-57cb1bbfe0c2 ro singleecho 'Loading initial ramdisk ...'initrd /boot/initrd.img-2.6.35-27-generic}复制一份在这些结构前粘贴,注意必须贴在### BEGIN /etc/grub.d/10_linux ###……### END /etc/grub.d/10_linux ###里面,并将粘贴出来的结构中的linux /boot/vmlinuz-2.6.35-27-genericinitrd /boot/initrd.img-2.6.35-27-generic改成你的内核文件地址和initrd文件地址linux /boot/vmlinuz-2.6.35.11-mykernelinitrd /boot/initrd.img-2.6.35.11最好把其他所有版本相关信息号改成2.6.35.11(新编译的版本号),以便在Grub菜单选择比如改成menuentry 'Ubuntu, with Linux 2.6.35.11' --class ubuntu --class gnu-linux --class gnu --class os {recordfailinsmod part_msdosinsmod ext2set root='(hd1,msdos1)'search --no-floppy --fs-uuid --set 71a50d19-caef-4dff-9a7a-57cb1bbfe0c2linux /boot/vmlinuz-2.6.35.11-mykernelroot=UUID=71a50d19-caef-4dff-9a7a-57cb1bbfe0c2 ro quiet splashinitrd /boot/initrd.img-2.6.35.11}menuentry 'Ubuntu, with Linux 2.6.35.11 (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os {recordfailinsmod part_msdosinsmod ext2set root='(hd1,msdos1)'search --no-floppy --fs-uuid --set 71a50d19-caef-4dff-9a7a-57cb1bbfe0c2echo 'Loading Linux 2.6.35.11 ...'linux /boot/vmlinuz-2.6.35.11-mykernelroot=UUID=71a50d19-caef-4dff-9a7a-57cb1bbfe0c2 ro singleecho 'Loading initial ramdisk ...'initrd /boot/initrd.img-2.6.35.11}注意检查一下/boot/目录下是否存在上面这两个文件,如果没有,证明上面的几部还没成功还有就是这些menuentry的顺序,有些系统启动引导时会直接进入第一个menuentry,如果第一个menuentry不是你想进的内核,则需要在开机时按Shift进入GRUB引导菜单选择内核。
实验二增加系统调用实验报告一修改系统文件1.在系统调用表中添加相应表项# cd /usr/src/linux-2.4/arch/i386/kernel# vi entry.S添加.long SYMBOL_NAME(sys_pedagogictime)见图1:2. 添加系统调用号# cd /usr/src/linux-2.4/include/asm# vi unistd.h添加# define __NR_pedagogictime 259见图2:3. 在文件最后添加一个系统服务例程# cd /usr/src/linux-2.4/kernel# vi sys.c添加sys_pedagogictime见图三二.编译内核# cd /usr/src/linux-2.4# make mrproper# make xconfigBlock devices → Loopback device support 选YSCSI support → SCSI low-level drivers → BusLogic SCSI support 选YFile systems → Ext3 journallingfile system support 选YNTFS file system support 选YSave and exit# make dep# make clean# make bzImage# make modules# make modules_install从/etc/modules.conf中删除BusLogic的加载项#alias scsi_hostadapter BusLogic /* 否则make install时总报错:No module BusLogic found for kernel 2.4.22 */ # cd /usr/src/linux-2.4# make install三将新内核和System.map拷贝到/boot目录下# cp /usr/src/linux-2.4/arch/i386/boot/bzImage /boot/vmlinux-2.4.20# cp /usr/src/linux-2.4/ System.map /boot/System.map-2.4.20# cd /boot# rm –f System.map# ln –s System.map-2.4.20 System.map四修改Grub启动管理器# cd /boot/grub# vi menu.lst修改menu.lst文件,将Red Hat Linux (2.4.20-8custom)部分中的root=LABEL=/改为root=/dev/sda2修改前见图四修改后见图五五重启系统:# reboot重启后显示如图六:选择Red Hat Linux (2.4.20-8custom),回车六编辑用户空间的测试程序:.运行结果:。
Linux系统增加系统调用之前的一段时间就做过Linux系统的系统调用的实验,但是一直无法最终实现,这几天又重新捣鼓了一下,最终终于成功实现了在Linux中增加系统调用,在此本人使用的Linux 系统为Red Hat Linux 9.0,系统内核为linux-2.4.80的版本。
下面就讲述一下个人的实验经过。
一、系统文件修改进入Red Hat Linux 9.0后,右击桌面,打开终端,在终端中输入cd命令到内核目录下:[root@localhost root]#cd /usr/src/linux-2.4如下图所示:图1首先,进入/usr/src/linux-2.4/kernel目录,用ls查看该目录下的文件,找到其中的sys.c 文件,如下所示:图2若在kernel目录下找不到sys.c文件,说明在安装的时候没有将内核编译工具以前装上,可以导入安装光盘,双击打开进行系统工具的添加。
找到该文件后,使用命令:[root@localhost kernel]#gedit sys.c打开文件,并将要增加的系统调用写入其中,如下所示:图3图中选中部分内容即为本次本人所增加的系统调用,因为这是一次实验,所以增加的内容显得比较简单,只是调用一个foo函数,输出一个整数,在添加的内容中,有几点要特别注意:1、在sys.c中,增加的系统调用的函数名必须以“sys_”开头2、输出语句应为printk()而不是printf(),这和之前所认识的输出语句有所不同3、函数前面要带上asmlinkage标记修改完sys.c文件之后,进入/usr/src/linux-2.4/include/asm-i386目录下,找到unistd.h文件,并在其中添加刚才在sys.c文件中添加的函数的系统调用号,如下所示:、图4图5完成这一步骤之后,接下来要修改第三个文件,也是最后一个文件,entry.S,该文件在/usr/src/linux-2.4/arch/i386/kernel目录下,如图所示:图6打开该文件,并在该文件中添加之前写入sys.c文件中的系统函数的清单号,如下图所示:图7保存退出后,自此则完成了对增加系统调用所涉及的的要修改的文件的修改,完成这步以后,就要开始对修改后的内核进行编译了。
操作系统实验一:向Linux 内核增加一个系统调用一、实验目的通过实验,熟悉Linux 操作系统的使用,掌握构建与启动Linux 内核的方法;掌握用户程序如何利用系统调用与操作系统内核实现通信的方法,加深对系统调用机制的理解;进一步掌握如何向操作系统内核增加新的系统调用的方法,以扩展操作系统的功能。
二、实验类型设计型实验三、预习要求已完成操作系统相关课程,了解操作系统结构。
四、实验设备与环境PII以上电脑一台,已安装Linux操作系统,GCC或其他C语言编译环境。
五、实验原理内核:内核是整个操作系统的最底层,它负责了整个硬件的驱动以及提供了各种系统所需的内核功能,包括防火墙机制,是否支持LVM或Quota 文件系统,以及进程和内存管理和通信功能。
其实内核就是系统上面的一个文件而已,它包含了驱动主机各项硬件的检测程序与驱动模块。
内核文件通常被放置在/boot/vmlinuz中。
(uname –r 命令:显示内核版本信息) 内核模块:由于现在硬件更新速度太快,如果我的内核比较旧,我换了新的硬件,内核肯定无法支持,怎么办?重新拿一个新的内核来处理吗?内核编译的过程是很麻烦的。
为了这个缘故,Linux很早之前就已经开始使用所谓的模块化设置了。
即将一些不常用的类似驱动程序的内容独立出内核,编译成为模块,然后,内核可以在正常运行的过程当中加载这个模块到内核。
这样,在不需要改动内核的前提之下,只要编译出适当的内核模块并加载它,Linux就可以使用新的硬件。
模块被放置在/lib/modules/$(uname -r)/kernel中。
内核编译:内核其实是一个文件,由源代码编译而成的,开机读完BIOS 并加载MBR内的引导程序后,就开始加载内核到内存当中,所以要将它编译成系统可以认识的数据才行。
六、实验1. Linux 环境下的C 或C++编译和调试工具的使用2. 向Linux 内核增加新的系统调用,系统调用名称和功能自行定义3. Linux 新内核的编译、安装和配置4. 编写应用程序以测试新的系统调用并输出测试结果七、实验步骤1、开启电脑,从实验室共享了文件的机器上拷贝内核源码文件linux-2.6.30.tar.gz,以及ncurses-devel-5.5-24.20060715.i386.rpm文件。
操作系统实验报告----- Linux下的系统调用计算机10-4 赵俊楠10081407实验目的:实现多个系统调用实验实验内容:添加简单系统调用、添加随机抽牌系统调、用模块添加系统调用实验步骤:(我是将三个系统调用添加完毕后一起编译的)1.在usr/src/linux-2.4/include/asm i386/unistd.h中添加#define __NR_print_info 259和#define __NR_rank 2602.在usr/src/linux-2.4/arch/i386/kernel/entry.S中添加.long SYMBOL_NAME(sys_print_info)和.long SYMBOL_NAME(sys_rank);3.在usr/src/linux-2.4/kernel中添加asmlinkage int sys_rank(int value,int suit){if (value==1) return (int)(4*13+suit);else return (int)(4*(value-1)+suit);};和asmlinkage int sys_print_info(int testflag){printk(KERN_EMERG " It's my syscall function!\n");return 0;}4.在usr/src/linux-2.4/kernel/ksyms中添加#ifndef __mips__EXPORT_SYMBOL(sys_call_table);#endif至此,三个实验的系统调用添加完毕下面开始编译内核。
5.make cleanmake mrpropermake oldconfigmake depmake bzImagemake modulesmake modules_installmake install在添加系统调用时候一定要专心、仔细,否则在编译的时候会出现错误,改起来很麻烦!!6.重启Linux后,显示界面如下(没有改内核版本号)7.进入新内核后不要忘了将#define __NR_print_info 259和#define __NR_rank260添加到中8.然后编写三个测试程序分别测试新的系统调用结果如下图:关于test_print_info关于card关于call和test_call实验总结:本次实验的内容涉及到Linux的系统调用。
实验一添加一个新的系统调用
一、实验目的
理解操作系统内核与应用程序的接口关系;加深对内核空间和用户空间的理解;学会增加新的系统调用。
二、实验内容与要求
首先增加一个系统调用函数,然后连接新的系统调用,重建新的Linux内核,用新的内核启动系统,使用新的系统调用(2.4内核和2.6内核任选一个)
三、实验指导(2.6版本)
⑴获得源代码(本次实验的内核版本是2.6.22.5,必须是root用户)
1.从教育在线上下载内核源代码到本地磁盘;保存在/usr/src目录下
2.进入终端,输入命令cd /usr/src 进入/usr/src目录(可以输入ls命令会发现目录下有一个名为LINUX_2_6_22_5.TAR.BZ2的压缩文件)
3.当前目录下(/usr/src)输入命令tar –xjvf LINUX_2_6_22_5.TAR.BZ2 解压缩源代码,命令执行完毕后,会出现/usr/src/linux-2.6.22.5文件夹
4.修改文件夹下的3个文件
第一,编辑/usr/src/linux-版本号/kernel/sys.c文件,添加函数:
asmlinkage long sys_mycall(long number)
{
printk(“call number is %d\n”,number);
return number;
}
第二,修改/usr/src/linux-版本/include/asm-i386/unistd.h
添加一行#define __NR_mycall 324 到当前的最大系统调用号之后,比如原来最大的是323,在323的这一行之后加上一行#define __NR_mycall 324
修改#define NR_systemcalls 的值,改成原来的值+1,比如原来是324 改成325
第三,编辑/usr/src/linux-版本/arch/i386/kernel/syscall_table.S,在文件最后加上一行:.long sys_mycall
5.重新编译内核
在终端输入命令,进入源代码文件夹,cd /usr/src/linux-2.6.22.5 依次执行如下命令:make mrproper
make clean
make xconfig (自己配置内核,出现图形对话框后,直接点保存,关闭)
make
(耗时最长,大约20分钟)
make modules_install (安装模块)
以上命令执行完毕后,会在当前目录下生成一个名为System.map的文件,会在/usr/src/linux-版本号/arch/i386/boot/下生成一个bzImage文件。
在终端执行以下命令:
cp /usr/src/linux-版本号/arch/i386/boot/bzImage /boot/vmlinuz-版本号(拷贝内核镜像)cp /usr/src/linux-版本号/System.map /boot/System.map-版本号(拷贝符号表)
cd /boot (进入/boot目录)
mkinitrd initrd-版本号.img 版本号(如mkinitrd initrd-2.6.22.5.img 2.6.22.5)(生成临时根文件)
6.编辑启动配置文件grub
编辑/boot/grub/grub.conf 在grub.conf文件中,每一个title标签表示一个启动项,仿照第一段title的写法,编写新内核的启动项,其中kernel和initrd使用新拷贝过来的vmlinz—版本号文件和initrd-版本号.img文件。
(可以先复制一段title的内容,修改title后面的启动名称,修改kernel 和initrd 后面指定的启动文件,如下图所示,选中的内容是修改后的)
图1 原来的grub配置文件
图2 修改后的grub配置文件
7.重新启动系统,使用新生成的内核。
8.编写测试程序,测试新系统调用。
testcall.c
int main()
{
syscall(324,100); /*324是新添加的系统调用号,100是参数*/
return 0;
}
终端编译gcc testcall.c –o testcall
运行./testcall
查看结果:终端运行命令dmesg 会看到在最后一行输出call number is 100
四、2.4内核下添加系统调用的方法(添加系统调用必须是root用户)
1.获得linux源代码
在linux系统的/usr/src目录下有系统的源代码。
(如果没有,可以先下载,然后解压到此目录下),解压完毕后,源代码的目录就是/usr/src/linux-版本号
2.添加自定义的系统调用实现函数
编辑/usr/src/linux-版本号/kernel/sys.c文件,添加函数:
asmlinkage long sys_mycall(long number)
{
printk(“call number is %d\n”,number);
return number;
}
3.添加系统调用号
编辑/usr/src/linux-版本号/include/asm-i386/unistd.h文件,在最大系统调用号的最后添加一项
#define __NR_mycall 259 (假设当前的最大系统调用号是258)
4.在系统调用入口表中添加相应的项。
编辑/usr/src/linux/arch/i386/kernel/entry.S 文件
添加long SYMBOL_NAME(sys_mycall)
5.重新编译内核
在源代码目录下有一个Makefile文件,(/usr/src/linux-版本号/Makefile),Makefile 文件的前四行是内核的版本号,如下:
VERSION=2
PATCHLEVEL=4
SUBLEVEL=20
EXTRAVERSION=-8 (假设内核版本是2.4.20-8)
在修改内核后,编译内核之前,可以修改Makefile的内核版本号信息,比如可以将EXTRAVERSION项改成-8a,那么重新编译内核后,新内核的版本号将是2.4.20-8a
以下是编译内核的步骤:
首先进入源代码目录/usr/src/linux-版本号,依次运行以下命令:
make mrproper 确保没有不正确的.o文件及文件的相互依赖
make clean 清除旧的编译结果
make config 或者make menuconfig 或者make xconfig //配置内核
make dep 生成依赖关系
make bzImage 编译内核映象
make modules 编译内核模块
make modules_install 安装内核模块
以上命令成功完成后,将生成的内核镜像文件和符号表拷贝到/boot目录下。
cp arch/i386/boot/bzImage /boot/vmlinuz-版本号(拷贝内核镜像)
cp System.map /boot/System.map-版本号(拷贝符号表)
cd /boot (进入/boot目录)
mkinitrd initrd-版本号.img 版本号(如mkinitrd initrd-2.4.20-8a.img 2.4.20-8a)(生成临时根文件)
6.编辑启动配置文件grub
编辑/boot/grub/grub.conf 在grub.conf文件中,每一个title标签表示一个启动项,仿照每一段title的写法,编写新内核的启动项,其中kernel和initrd使用新拷贝过来的vmlinz—版本号文件和initrd-版本号.img文件。
7.重新启动系统,进入新生成的内核。
8.编写测试程序,测试新系统调用。
testcall.c
int main()
{
syscall(259,100); /*259是新添加的系统调用号,100是参数*/
return 0;
}
终端编译gcc testcall.c –o testcall
运行./testcall
查看结果dmesg 会看到输出call number is 100。