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()

posted @ 2020-11-07 18:37  侯蕴哲  阅读(125)  评论(0编辑  收藏  举报