2020-2021-1 20209304 《Linux内核原理与分析》第五周作业
一、实验:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
1、API time()获取时间范例
代码:
#include<time.h>
int main(){
time_t tt;
struct tm *t;
tt = time(NULL);
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d:\n",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
return 0;
}
编译结果:
2、使用C语言内嵌汇编实现time()
代码:
#include<stdio.h>
#include<time.h>
int main(){
time_t tt;
struct tm *t;
asm volatile(
"movl $0,%%ebx;\n\t"
"movl $0xd,%%eax;\n\t"
"int $0x80;\n\t"
"movl %%eax,%0;\n\t"
:"=m"(tt)
);
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d:\n",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
return 0;
}
在运行中出现了段错误,上网查找也没有找到解决办法,最后在同学的指导下,直到是堆栈溢出导致的。
修改了代码:
编译通过:
3、含两个参数的系统调用
C语言调用rename系统调用:
#include<stdio.h>
int main()
{
char *oldname = "hello.c";
char *newname = "new1hello.c";
int ret;
ret=rename(oldname,newname);
if(ret==0)
printf("Rename successfully!\n");
else
printf("Unable to rename the file!\n");
return 0;
}
汇编语言调用rename系统调用:
#include <stdio.h>
int main()
{
char* oldname="hello.c";
char* newname="new1hello.c";
int ret;
asm volatile(
"movl %1,%%ebx\n\t"
"movl %2,%%ecx\n\t"
"movl $0x26,%%eax\n\t"
"int $0x80\n\t"
:"=a"(ret)
:"b"(oldname),"c"(newname)
);
if(ret==0)
printf("Rename Successfully!\n");
else
printf("Unable to rename the file!\n");
return 0;
}
运行结果:
二、学习收获
1、什么是系统调用 :操作系统为用户态进程与硬件设备进行交互提供了一组接口。
2、用户态、内核态、中断和系统调用打交道的方式是通过库函数的方式,库函数将系统调用给封装起来了
3、linux系统下如何区分内核态与用户态
在内核态:cs:eip可以是任意的地址,4G的内存地址空间
在用户态:cs:eip只能访问0x00000000—0xbfffffff的地址空间
4、系统调用的三层皮:
第一层:API
第二层:中断向量对应的
第三层:系统调用有不同种类的服务程序
5、系统调用的意义:
(1)把用户从底层的硬件编程中解放出来
(2)极大地提高了系统的安全性
(3)使用户程序具有可移植性
系统调用的工作机制:
1、用户态中的xyz()函数就是系统调用所对应的系统API;
2、在这个API中将系统调用封装好,并在执行时触发int 0x80这个中断。对应内核态的system_call();
3、system_call()中可能会执行中断服务程序sys_xyz()