重庆大学操作系统实验一(系统调用)
计算机操作系统实验指导计算机系统调用

使用内核编译法添加系统调用
为了验证系统调用是否成功,编写验证代码如下。 #include <stdio.h> #include <linux/kernel.h> #include <sys/syscall.h> #include <unistd.h> int main() { long int a = syscall(三三三); printf("System call sys_helloworld reutrn %ld\n", a); return 0; }
如图地执行结果,我们得到sys_call_table地址:ffffffffabe00一a0 三. 编写Makefile文件,可参考实验指导书地内容。 四. 编译并装入模块 # sudo make //编译 # sudo insmod hello.ko //装入模块 # lsmod //该命令查看所有模块,用以检查hello是否被装入系统 # sudo rmmod hello.ko //卸载模块
三三三 六四 helloworld
sys_helloworld
使用内核编译法添加系统调用
六. 配置内核 # cd /usr/src/linux-四.一六.一0 # sudo make mrproper # sudo make clean # sudo make menuconfig 七. 编译与安装内核(与第七章类似) # sudo make -j八 # sudo make modules -j八 # sudo make modules_install # sudo make install 八. 重启系统 # uname -r 查看此时地内核版本
编译验证代码: # gcc hello.c
实验一 操作系统系统调用 实验报告

Linux系统调用实验报告一、实验目的深入理解操作系统是虚拟机二、实验方法利用UNIX/LINUX所提供的系统调用来编写C语言程序,程序中要体现出一些典型的系统调用(函数)三、实验任务编写一个C语言程序,该程序将一个存放了一系列整数的文本文件进行排序,每个整数占据文件的一行,排序的结果存放到一个新的文件之中。
源文件和目标文件的文件名由命令行输入。
例如:假设可执行文件的文件名是sort,源文件与目标文件的名字分别是data和newdata,那么命令行的情形为如下所示内容:./sort data newdata四、实验要点命令行参数传递、系统调用的使用五、实验内容5.1 命令行参数传递C语言标准规定,C语言程序的入口函数(main 函数)的定义如下:int main(int argc, char** args)其中,argc 表示args这个指针数组元素的数量,而args则储存程序的命令行参数,其中,args[0]储存着可执行文件的文件名,args[1]储存第一个命令行参数,如此类推。
以在命令行中输入./sort data newdata 为例,args[0]的值为“./sort”,args[1]的值为”data”,args[2]的值为”newdata”。
5.2 打开文件在操作系统中,需要对一个文件进行读写操作前需要打开文件。
open这个系统调用的作用就是打开指定的文件,并返回一个文件描述符。
通过这个文件描述符可以对文件进行读写操作。
open系统调用的定义如下:int open(const char* pathname, int flags)int open(const char* pathname, int flags, mode_t mode)其中,pathname是要打开文件的路径,flags参数指定文件打开的方式,这个参数可以通过多个常数的位或运算传递多种的方式,其中包括只读(O_RDONLY),只写(O_WRONLY),读写(O_RDWR),创建文件(O_CREAT),追加方式打开(O_APPEND);当使用O_CREAT方式打开文件时,可以通过一个额外的mode参数来控制所创建文件的权限。
操作系统实验-系统调用基础

实验一、系统调用基础一、实验题目在第2.3节中,我们描述了一个复制一个文件内容的程序到目标文件。
这个程序的工作原理是首先提示用户输入源文件和目标文件的名称。
使用以下命令编写这个程序Windows或POSIX API。
确保包含所有必要的错误检查,包括确保源文件存在。
一旦你正确地设计和测试了程序,如果你使用支持它的系统,使用跟踪的实用程序运行程序系统调用。
Linux系统提供strace实用程序,Solaris和Mac OS X系统使用dtrace命令。
和Windows系统一样如果不提供这些功能,您将不得不通过Windows进行跟踪版本本程序使用调试器。
二、相关原理与知识(完成实验所用到的相关原理与知识)Linux 系统调用相关基础知识Linux C 文件读写相关基础知识strace的使用三、实验过程(清晰展示实际操作过程,相关截图及解释)为了模拟cp命令,我们主要通过命令行来传递参数,对于参数数量不符合的输入则直接终止程序。
if (argc != 3){puts("Usage: ./mycp source_file_path destination_file_path");exit(0);}对于要被拷贝的源文件,比较常规的思路是逐字节读入,若是读到EOF 则说明读取到了文件末尾;但是在Linux 下我们可以直接使用fstat() 函数将一个文件的所有相关信息记录到一个stat结构体中,通过其st_size成员直接获取其长度,之后就可以直接通过read(fd, buf, st.st_size) 读入文件内容。
src_fd = open(argv[1], O_RDONLY);if (src_fd == -1){puts("Failed to open the source file!");exit(-1);}printf("fd of src: %d\n", src_fd);fstat(src_fd, &src_st); // get source file lengthbuf = (char*) malloc(sizeof(char) * src_st.st_size);if (buf == NULL){puts("Malloc error!");exit(-1);}read(src_fd, buf, src_st.st_size);写入文件则可以通过fwrite 完成,相比起我们手动通过文件描述符对文件进行操作而言,由glibc封装的相关文件操作更为方便,这里便不再赘叙。
实验2.4_系统调用_实验报告

<系统调用>实验报告题目: 系统调用1、实验目的向现有Linux内核加入一个新的系统调用从而在内核空间中实现对用户空间的读写。
例如,设计并实现一个新的内核函数mycall( ),此函数通过一个引用参数的调用返回当前系统时间,功能上基本与gettimeofday( )相同。
也可以实现具有其它功能的系统调用。
2、实验内容与步骤1. 添加新调用的源代码在/usr/src/linux-3.16.6-10/kernel/sys.c中添加相应的调用代码asmlinkage int sys_mycall(struct timeval *tv){struct timeval ktv;MOD_INC_USE_COUNT;do_gettimeofday(&ktv);if (copy_to_user(tv,&ktv,sizeof(ktv))){MOD_DEC_USE_COUNT;return -EFAULT;}MOD_DEC_USE_COUNT;return 0;}2. 连接系统调用a、修改/usr/src/linux-3.16.6-10/include/asm-i386/unistd.h,在系统调用列表后面相应位置添加一行#define _NR_mycall 222新增加的调用号位222b、修改/usr/src/linux-3.16.6-10/arch/i386/kernel/entry.S在sys_call_table[]清单最后添加一行.long SYMBOL_NAME(sys_mycall)3. 重建新的Linux内核cd /usr/src/linux-3.16.6-10/make mrpropermake oldconfigmade depmake cleanmake bzImagemake modulesmake modules_installmake install保存配置文件, 开始编译内核:4. 重建引导信息a、在/boot/grub/grub.conf中自己添加一条新的启动选项,并使该选项指向vimlinuz-3.16.6-10customb、重新安装grub5. 重新引导从新的内核进入6. 修改/usr/lib/bcc/include/unistd.h,在系统调用列表后面相应位置添加一行#define _NR_mycall 2227.编写程序测试test.c:#include <linux/unistd.h>#include <linux/time.h>#include <stdio.h>_syscall1(int,mycall,struct timeval *,thetime)main(){struct timeval gettime;struct timeval mycalltime;gettimeofday(&gettime,NULL);mycall(&mycalltime);printf("gettimeofday:%d%d\n",_sec,_usec);printf("mycall:%d%d\n",_sec,_usec);}编译运行得到如下结果:参考程序当中有若干需要注意的地方, 在编译的时候遇到错误和警告, 提示没有声明NULL需要加上#include<stdio.h>头文件, 由程序的输出结果相同可知, mycall和gettimeofday具有相同的功能.实验结果正确.。
操作系统中的系统调用技术研究

操作系统中的系统调用技术研究一、概述操作系统中的系统调用技术是指用户程序如何通过操作系统提供的服务来完成特定功能的过程。
系统调用可以使用户程序访问操作系统内部的资源,如文件、网络和系统设备等。
本文就系统调用的概念、原理和实现方式进行阐述。
二、系统调用的概念1.定义系统调用是指用户程序通过软件中断或陷阱机制,请求操作系统提供服务的过程,是用户程序和操作系统之间的接口。
系统调用中所提供的服务包括进程管理、内存管理、文件管理、设备管理、网络管理等方面。
2. 作用系统调用允许用户程序访问系统资源并与外部环境进行交互,保证了程序的正常运行。
系统调用提供了一组标准的接口,使程序员能够方便地使用操作系统的服务。
同时,系统调用还实现了保护机制,保护了系统资源不受用户程序的非法访问。
三、系统调用的原理1.特权级系统调用的实现离不开特权级的限制。
特权级是指对系统资源的访问级别,可以用于防止用户程序对系统的非法访问。
在x86平台上,CPU提供了4个特权级,级别0是最高特权级,级别3是最低特权级。
在系统调用时,用户程序通过陷阱指令将CPU的特权级别转为0级,并请求操作系统提供服务。
2.软中断系统调用的实现通常采用软中断的方式。
软中断是指通过CPU 执行中断指令来触发中断服务程序并产生中断。
中断服务程序可以是系统调用处理程序,负责响应用户程序的请求并进行处理。
软中断通常由int指令触发,该指令将依次执行中断描述符、中断向量入口和中断服务程序。
在执行中断服务程序时,根据系统调用的类型以及参数传递方式进行处理,最后将结果返回用户程序。
四、常见的系统调用1.进程管理进程管理包括创建进程、终止进程、进程切换、进程通信等操作。
其中,常见的系统调用有fork、exec、wait和kill等。
fork:创建一个与当前进程完全一样的新进程。
exec:在当前进程中启动新程序。
wait:等待当前进程的子进程退出。
kill:向指定进程发送信号。
《操作系统》上机实验一报告

《操作系统》上机实验一报告目录一、实验关键问题二、代码设计思路三、实现的关键代码四、程序运行结果五、实验总结一、实验关键问题1.1要求:编写一个Linux系统C程序,由父亲创建2个子进程,再由子进程各自从控制台接收一串字符串,保存在各自的全局字符串变量中,然后正常结束。
父进程调用waitpid等待子进程结束,并分别显示每个子进程的进程标识号和所接收的字符串。
1.2要求:父进程创建一子进程,父进程向子进程发送数据,子进程接收数据,并写入文件。
二、代码设计思路2.1 问题1.1的代码设计思路由父进程创建两个共享内存→分别创建两个子进程→提示用户输入信息,并将信息存到子进程各自对应的共享内存中→等待子进程结束→子进程结束后,父进程被唤醒并与共享内存连接→分别从这两个内存共享中获取数据,并把数据和对应的子进程PID输出到屏幕上→父进程结束2.2问题1.2的代码设计思路由父进程创建管道→创建子进程→父进程关闭读管道,获取用户输入的数据→把数据写入写管道中,关闭写管道→等待子进程结束,此时父进程挂起→子进程关闭写管道→子进程读取父进程放入读管道中的数据,显示数据到屏幕上→将数据写入文件“CP_file.txt”中→关闭读管道,关闭文件→结束子进程→父进程被唤醒后父进程也结束。
三、实现的关键代码3.1 问题1.1的实现代码#include <unistd.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/types.h>#include <sys/wait.h>#include <stdio.h>#include <stdlib.h>#define Key0 9876#define Key1 5432#define Size 2048 //Size表示共享内存大小,此处设置为2048int main(){int shmid1, shmid2;//共享内存的标识符//父进程创建共享内存shmid1和shmid2shmid1 = shmget(Key0, Size, IPC_CREAT|0600);shmid2 = shmget(Key1, Size, IPC_CREAT|0600);pid_t pid1, pid2;//子进程标识符char *shmaddr;//连接地址//父进程创建子进程pid1if ((pid1 = fork()) == 0){shmaddr = (char*)shmat(shmid1, NULL, 0);/*shmat()实现子进程pid1与共享内存shmid1的连接*/printf("Child process 1 is running now, enter a string:");/*请求用户输入一个字符串*/fgets(shmaddr, Size-1, stdin);/*fgets()将信息存到shmaddr所指的内存空间*/shmdt(shmaddr);/*shmdt()使该进程脱离该共享内存断,但并不删除该内存段*/return 0;}printf("\nWaitting for child process 1...\n");waitpid(pid1, NULL, 0);//等待子进程pid1结束printf("Child process 1 is over...\n");//父进程创建子进程pid2if ((pid2 = fork()) == 0){shmaddr = (char*)shmat(shmid2, NULL, 0);printf("Child process 2 is running now, enter a string:");fgets(shmaddr, Size-1, stdin);shmdt(shmaddr);return 0;}printf("\nWaitting for chils process 2...\n");waitpid(pid2, NULL, 0);printf("Child process 2 is over...\n\n");shmaddr = (char*)shmat(shmid1, NULL, 0); /*父进程与共享内存shmid1连接*/printf("Child process 1: PID=%d message: %s\n", pid1, shmaddr);/*屏幕显示共享内存shmid1的信息*/shmdt(shmaddr);shmctl(shmid1, IPC_RMID, NULL);//删除共享内存shmid1shmaddr = (char*)shmat(shmid2, NULL, 0);printf("Child process 2: PID=%d message: %s\n", pid2, shmaddr);shmdt(shmaddr);shmctl(shmid2, IPC_RMID, NULL);return 0;}3.2 问题1.2的实现代码#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#define maxsize 2048//maxsize表示传送的最大数据量,此处设置为2048 int main(){pid_t pid;//子进程标识符int pip[2];//管道描述符//创建管道if (pipe(pip) < 0)//管道创建失败{printf("Faile to create pipe!\n");return -1;}//创建子进程if ((pid = fork()) < 0)//子进程创建失败{printf("Faile to create child process!\n");return -1;}char buffer[maxsize];// 数据缓冲区FILE *file;// 文件描述符//子进程执行if ( pid==0 ){close(pip[1]);// 关闭写管道read(pip[0], buffer, maxsize);// 读取父进程发送的管道数据close(pip[0]);// 关闭读管道//屏幕输出子进程接收到得信息printf("Child process is running now, the received record:\n%s", buffer);if ((file=fopen("CP_file.txt", "w"))==NULL)/*打开CP_file.txt文件失败*/{printf("Error!Can't open CP_file.txt.\n");exit(1);}else{fputs(buffer, file);// 成功打开CP_file.txt文件,将数据写入文件中fclose(file);// 关闭文件return 0;}}//父进程执行else{close(pip[0]);// 关闭读管道printf("Parent process is running now, enter the record:\n");fgets(buffer, maxsize-1, stdin);// 接收用户输入的数据write(pip[1], buffer, maxsize);// 接收用户输入的数据close(pip[1]);// 关闭写管道waitpid(pid, NULL, 0);// 父进程等待子进程结束return 0;}}四、程序运行结果4.1 问题1.1的程序运行结果(图4.1所示)(图4.1)4.2 问题1.2的程序运行结果(图4.2所示)(图4.2)五、实验总结通过本次上机实验,我的收获很多。
操作系统实验一

重庆大学实验报告实验题目:多线程和多进程的管理与调度学院:计算机学院专业班级:年级: 2015 级姓名:学号:完成时间: 2017 年 11 月 1 日指导教师:重庆大学教务处制实验项目指导教师评定成绩表学号:姓名:班级:指导教师签名:年月日二、实验过程或算法(源程序)#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <pthread.h>#include <sys/types.h>#include <sys/wait.h>//线程1:求1~n 之间的素数void *MyThread1(void* in){int n; int h = 0, leap = 1,k,m, i;printf("input the value of n:\n"); //输入n 的值 scanf("%d",&n); printf("the prime between 1 ~ %d is: \n",n);for( int m = 2; m <= n; m++){ for( int i = 2; i<= m/2; i++){ if( m%i == 0 ){ leap= 0; break;if(leap){ printf("%4d",m);h++; if( h%10 == 0 )printf("\n");} leap =1; }printf("\n thread1 exit! \n"); //线程1 退出pthread_exit(0);}//线程2:生成Fibonacci 序列void *MyThread2(void* in){int fib0 = 0, fib1 = 1, fib2, i, N; printf("inputfib value N:\n"); //输入N 值scanf("%d",&N);printf("the fib sequence as following:\n");for( i = 0; i < N; i++){ if( i == 0 )printf("0 "); else if ( i == 1)printf("1 "); else { fib2 =fib0 + fib1; printf("%d ",fib2);fib0 = fib1; fib1 = fib2;} }printf("\n thread2 exit! \n"); //线程2 退出pthread_exit(0);}//4 号进程来创建2 个线程int MainThread4(){int ret1 = 0, ret2 = 0;pthread_t id1, id2; //定义两个线程id//调用pthread_create()函数来创建线程1ret1 = pthread_create(&id1, NULL, MyThread1, NULL); // ret1 == 1 表示创建失败;// ret1 == 0 表示创建成功;printf("The process %d exit\n",cpid);} exit(0);}int main(){int i;for(i = 2; i <= 3; i++){ pid_t child;child = fork();//创建失败if( child == -1 ){printf("Error happened in fork fuction!\n"); return 0;}三、实验结果及分析和(或)源程序调试过程。
操作系统上机实验报告

操作系统课程设计实验报告册班级:学号:姓名:教师:目录实验1 系统调用 (3)实验2 内核模块...................... . (6)实验3 Proc文件系统 (7)实验4 设备驱动 (9)实验编号 1 题目系统调用实验目的(1)了解为什么要进行系统调用(2)了解系统提供借口的目的(3)添加系统调用实验内容为Linux内核增加一个系统调用,并编写用户进程的程序来测试。
要求该系统调用能够完成以下功能:(1). 该系统调用有1个整型参数,接收输入自己的学号;(2). 若参数为奇数,则返回自己学号的最后5位。
如您的学号为13051007,则返回51007;(3). 若参数为偶数,则返回自己的学号的最后4位。
如您的学号为13051004,则返回1004。
报告正文1.实验设计1)第一步:解压缩内核源码包linux-2.6.32.60.tar.bz2到目录/usr/src下解压缩命令tar xvf linux-2.6.32.60.tar.bz2 /usr/src解压缩后在/usr/src中多了一个linux-2.6.32.60的文件夹,之后的修改源码的工作都是在这个文件夹中进行。
2)第二步:修改系统调用表文件linux-2.6.32.60/arch/x86/kernel/syscall_table_32.S在文件中最后一组.long代码后添加一行.long sys_mycall3)第三步:修改系统调用号文件,增加自己函数的系统调用号,并将系统总调用号增加。
linux-2.6.32.60/arch/x86/include/asm/unistd_32.h在文件最后增加系统调用#define __NR_mycall 337 //自己函数的调用号同时修改系统调用函数总数,这是可以调用的编号上限#define NR_syscalls 3384)第四步:增加系统调用声明,修改文件linux-2.6.32.60/include/linux/syscalls.h在文件后添加代码5)第五步:添加系统调用函数的实现,修改文件linux-2.6.32.60/kernel/sys.c 6)第六步:内核编译运行结果如下:dmesg命令查看printk()输出:实验编号 2 题目内核模块实验目的(1)理解linux内核模块优缺点及简单原理(2)了解内核模块的相关作用(3)熟悉内核模块的几个步骤(4)编译内核模块实验内容题目一编写一个内核模块;编译该模块;加载、卸载该模块;题目二用内核模块的方式为系统添加一个系统调用具体要求同专题一报告正文题目一:编写相应的hello.c文件以及Makefile文件,编译加载该模块:卸载该内核模块:查看内核模块运行结果:题目二编写相应的系统调用程序make实验编号 3 题目 Proc 文件系统实验目的(1)理解proc文件系统的作用(2)了解proc文件系统中的重要部分文件(3)了解proc文件系统与内核模块的交互实验内容(1)编写一个程序,用来读取和修改内核参数(任意参数即可,不涉及到内核编程,只需要使用标准C库中的函数)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
重庆大学
学生实验报告
实验课程名称操作系统原理
开课实验室重庆大学DS1501
学院软件工程年级2013 专业班
学生姓名学号
开课时间 2015 至 2016 学年第一学期
重庆大学软件学院制
《操作系统原理》实验报告
三、使用仪器、材料(软硬件开发环境)
Notepad++
expenv
四、实验步骤(实现的过程)
在下列四个文件内添加系统调用
U1、在epos/app/syscall-wrapper.S末尾,加入汇编语言接口“WRAPPER(time)”
U2、在epos/app/syscall.h中,加入C语言接口“time_t time(time_t *loc);”
U3、在epos/app/main.c中调用该系统调用,并打印出结果
•要测试loc分别为NULL和非NULL两种情况
machdep.c中添加函数
//计算需要的秒数
/*变量g_startup_time,它记录了EPOS启动时,距离格林尼治时间1970年1月1日午夜的秒数
变量g_timer_ticks,记录了EPOS启动以来定时器中断的总次数
宏定义HZ,是定时器每秒钟中断的次数,即定时器中断的频率*/
typedeflong time_t;
time_t sys_time(){
return g_startup_time+g_timer_ticks/HZ;
}
以及
//实验一系统调用
//ctx->eax为系统调用的返回值
//ctx->esp为用户栈的栈顶指针
case SYSCALL_time:
{
time_t*loc=*(time_t**)(ctx->esp+4);//一个参数
ctx->eax=sys_time();
if(loc!=NULL)
*loc=ctx->eax;//统计的秒数存到loc所指内存中
break;
}
主函数调用:
time_t*ptime=NULL;
printf("When loc is NULL\n");
printf("The time from 1970.1.1:%d\n",time(ptime));
time_t m_time=0;
printf("When loc is not NULL\n");
printf("Before syscall,the value of *loc:%d\n",m_time);
printf("The time from 1970.1.1:%d\n",time(&m_time));
printf("After syscall,the value of *loc :%d\n",m_time);
五、实验结果及分析(实现的效果,包括屏幕截图、系统总体运行情况和测试情况等)。