linux实验_添加系统调用-完整版

合集下载

编译内核-新增Linux系统调用过程

编译内核-新增Linux系统调用过程

一、题目:新增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和↑键出现开机启动项(如果是真机开机一般会自动出现开机启动项),选择新建的内核版本进入。

实验06 增加系统调用功能

实验06 增加系统调用功能

7、在汇编程序中使用系统调用 、
编写汇编程序, 编写汇编程序,见下图 编译
as –o asm.o asm.s ld –o asm asm.o
运行பைடு நூலகம்/asm 运行
8、在汇编程序中使用自己创建的系统调用 、
替换eax中的系统调用号 中的系统调用号 替换
9、在C程序中使用系统调用 、 程序中使用系统调用
参照lib/目录下库函数实现方法在 目录下库函数实现方法在libc库中增加 参照 目录下库函数实现方法在 库中增加 新系统调用库函数sethostname() 新系统调用库函数 示例: 示例:
#define _LIBRARY #include <unistd.h> _syscall2(int, sethostname, char *, name, int, len);
4、修改系统调用汇编程序 、
修改sys_call.s程序第 行,将内核系统调用 程序第61行 修改 程序第 总数nr_system_calls增1 总数 增
5、重新编译内核 、
参考实验: 系统中编译0.12内核 参考实验:在Linux0.12系统中编译 系统中编译 内核
6、增加新系统调用库函数 、
实验内容
增加系统调用功能
1、编制系统调用处理函数 、
例如:函数名sys_sethostname2 例如:函数名 放在kernel/sys.c程序中 放在 程序中 函数代码参加P295 函数代码参加 示例: 示例:
int sys_sethostname2(char *name, int len) { …… return 0; }
编写c程序 编写 程序 编译 运行
实验小结
3、添加外部函数声明 、

添加系统调用实验报告

添加系统调用实验报告

一、构建基本的实验环境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内核增加一个系统调用一、背景介绍操作系统是计算机硬件与应用程序之间的接口,负责管理和调度计算机系统的各种资源,并提供用户与计算机系统的交互界面。

内核是操作系统的核心部分,负责管理和分配计算机系统的资源,执行各种任务。

系统调用是操作系统提供给应用程序的一种接口,可以让应用程序访问内核提供的功能,例如文件操作、进程管理、网络通信等。

在一些情况下,我们可能需要在LINUX内核中增加新的系统调用,以满足特定的需求。

本文将介绍如何向LINUX内核增加一个系统调用的具体步骤。

二、增加系统调用的步骤1.编写系统调用的具体实现代码首先,我们需要编写一个具体的系统调用的实现代码。

在LINUX内核中,系统调用的实现代码通常位于内核的/syscalls目录下。

我们可以在该目录下新建一个.c文件,编写我们自己的系统调用代码。

2.修改内核源代码3.更新系统调用表每个系统调用都在内核中有一个唯一的标识符,存储在一个叫做系统调用表的地方。

我们需要更新系统调用表,将新增的系统调用添加到表中。

这样,用户程序才能够通过系统调用号来调用新增的系统调用。

4.重新编译内核在修改完内核源代码后,我们需要重新编译内核。

这通常涉及到一些繁琐的步骤,例如配置内核选项、编译内核、安装内核等。

在重新编译内核之后,我们需要重新启动计算机,使新的内核生效。

5.修改用户程序最后,我们需要修改用户程序,以便能够调用新增的系统调用。

用户程序通常是通过C语言编写的,我们可以在用户程序的代码中添加对新增系统调用的调用代码。

三、实验结果在完成上述步骤后,我们就成功地向LINUX内核增加了一个系统调用。

用户程序可以通过系统调用调用自己新增的系统调用,从而实现特定的功能。

总结:本文介绍了向LINUX内核增加一个系统调用的具体步骤,包括编写系统调用的具体实现代码、修改内核源代码、更新系统调用表、重新编译内核和修改用户程序。

在实施这些步骤之前,我们需要对操作系统和内核的相关概念有一定的了解,并具备一定的编程能力。

增加系统调用实验报告(3篇)

增加系统调用实验报告(3篇)

第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. 修改系统调用表接下来,我们需要修改内核源代码中的系统调用表,以注册我们创建的系统调用。

(完整word版)Linux内核中增加一个系统调用

(完整word版)Linux内核中增加一个系统调用

选题要求:在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内核模块法内核模块可以作为独立程序来编译的函数和数据类型的集合。

操作系统实验 为linux添加一个系统调用

操作系统实验 为linux添加一个系统调用

进程控制的基础
Linux进程创建及分析
第一个进程事实上就是Linux kernel本身,像所有其 他的进程一样,Linux kernel本身也有代码段,数据段, 堆栈。只不过Linux kernel这个进程自己来维护这些段, 这一点是与其他进程不同的地方。第一个进程是唯一一个 静态创建的进程,在Linux kernel编写并且编译的时候创 建。 在Linux内核中,这个进程被称作init task/thread(pid 0)。 系统中其他的进程都通过复制父进程来产生,Linux 提供两个系统调用fork和clone来实现这个功能,广义上, 我们都叫它们fork( ),这也是Unix系统的传统叫法,表示 一个进程分叉又产生两个进程。对fork( )具体使用方法我 们稍后阐述。
关键点五
一般来说,在fork之后时父进程先执行还是子进程先执行 是不确定的。这取决于内核所使用的调度算法。如果要求父子 进程之间相互同步,则要求某种形式的进程之间通信。
进程的创建和销毁——exec理解
关键点一
fork( )创建了一个程序,但是如果这个子程序只能 局限在自身的代码段范围之中(不能去执行别的程序), 那么fork( )也就没有太多的实际意义。在Linux中,exec 调用用于从一个进程的地址空间中执行另外一个进程, 覆盖自己的地址空间。有了这个系统调用,shell就可以 使用fork+exec 的方式执行别的用户程序了。一个进程 使用exec执行别的应用程序之后,它的代码段,数据段, bss段和堆栈段都被新程序覆盖,唯一保留的是进程号。
进程的创建和销毁——fork分析
1. 为新进程分配一些基本的数据结构。具体到Linux,最重要的 比如一个新的进程好pid,一个task_struct和一个8K大小的联合 体(存放thread_info和内核栈)等。 2. 共享或者拷贝父进程的资源,包括环境变量,当前目录,打 开的文件,信号量以及处理函数等。 3. 为子进程创建虚拟地址空间。子进程可能跟父进程共享代码 段,数据段也可能采用COM(写时拷贝)的策略使fork( )的速 度和灵活性得到提高。 4. 为子进程设置好调度相关的信息,使得子进程在适当的时候 独立于父进程,能被独立调度。 5. fork( )的返回。对于父进程来说,for( )函数直接返回子进程的 pid;而对于子进程来说,是在子进程被第一次调度执行的时候, 返回0。

实验3:添加系统调用

实验3:添加系统调用

实验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);····}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验一添加一个新的系统调用
一、实验目的
理解操作系统内核与应用程序的接口关系;加深对内核空间和用户空间的理解;学会增加新的系统调用。

二、实验内容与要求
首先增加一个系统调用函数,然后连接新的系统调用,重建新的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。

相关文档
最新文档