2020-2021-1 20209308《Linux内核原理与分析》第五周作业

Linux 基础

实验四

一.实验过程

1.使用库函数API触发一个系统调用

1.1例子(time库函数)

	#include <stdio.h>
	#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:
",t->tm_year+1900,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
        return 0;
}

1.2例子内嵌汇编(time库函数)

#include <stdio.h>
#include <time.h>

int main(){
	time_t tt;
	struct tm *t;
	asm volatile(
		"mov $0,%%ebx
	"
		"mov $0xd,%%eax
	"
		"int $0x80
	"
		"mov %%eax,%0
	"
		:"=m"(tt)
		);
	t=localtime(&tt);
	printf("time:%d:%d:%d:%d:%d:%d:
",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
	return 0;
}

2.getpid()库函数

C语言直接调用,其中必须添加sys/types.h的头文件

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
int main(){
	int i=getpid();
	printf("my pid is: %d
",i);
	return 0;
}

内嵌汇编代码的getpid

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void){
	int i;
	asm volatile(
		"mov $0,%%ebx
	"//把ebx寄存器清零
		"mov $0x14,%%eax
	"//getpid的系统调用号是20
		"int $0x80
	"//触发系统调用
		"mov %%eax,%0
	"//通过eax寄存器返回系统调用值
		:"=m"(i)
	);
	printf("my pid is: %d
",i);
	return 0;
}

3.mkdir()函数

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(){
	int flag=-1;
	flag=mkdir("/home/qed/homework/05/mydir",0755);
	if(flag==-1)
		printf("u failed!
");
	else
		printf("u succeess!
");
	return 0;
}

内嵌汇编代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(){
	int flag=-1;
	char *dir="/home/qed/homework/05/mydir1";
	//flag=mkdir("/home/qed/homework/05/mydir",0755);
	asm volatile(
		"movl $0x27,%%eax
	"
		"movl %1,%%ebx
	"
		"int $0x88
	"
		"movl %%eax,%0
	"
		:"=m"(flag)
		:"c"(dir)
		);
	if(flag==-1)
		printf("u failed!
");
	else
		printf("u succeess!
");
	return 0;
}

二.遇到的问题

在mkdir_asm函数执行的时候遇到了问题

这个问题暂不知道如何解决,在getpid的代码中也遇到了相似的问题,但因在实验楼的环境中运行时未出现如上错误,但在自己的虚拟机上便会出现,起初认为是因为虚拟机是64位,实验楼为32位导致的问题,但是在虚拟机上用-m32命令也未起效。


三.系统调用汇总

内核分为用户态和内核态,在用户态下程序不内直接访问内核数据结构或者内核程序,只有在内核态下才可访问。请求内核服务的进程使用系统调用的特殊机制,每个系统调用都设置了一组识别进程请求的参数,通过执行CPU指令完成用户态向内核态的转换。
32位系统中,通过int $0x80指令触发系统调用。其中EAX寄存器用于传递系统调用号,参数按顺序赋值给EBX、ECX、EDX、ESI、EDI、EBP这6个寄存器。
64位系统则是使用syscall指令来触发系统调用,同样使用EAX寄存器传递系统调用号,RDI、RSI、RDX、RCX、R8、R9这6个寄存器则用来传递参数。
操作系统对于中断处理流程一般为(顺序有先后):
关中断:CPU关闭中段响应,即不再接受其它外部中断请求
保存断点:将发生中断处的指令地址压入堆栈,以使中断处理完后能正确地返回。
识别中断源:CPU识别中断的来源,确定中断类型号,从而找到相应的中断服务程序的入口地址。
保护现场所:将发生中断处理有关寄存器(中断服务程序中要使用的寄存器)以及标志寄存器的内存压入堆栈。
执行中断服务程序:转到中断服务程序入口开始执行,可在适当时刻重新开放中断,以便允许响应较高优先级的外部中断。
恢复现场并返回:把“保护现场”时压入堆栈的信息弹回原寄存器,然后执行中断返回指令(IRET),从而返回主程序继续运行。

原文地址:https://www.cnblogs.com/ppswaggy/p/13922390.html