zoukankan      html  css  js  c++  java
  • 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),从而返回主程序继续运行。

  • 相关阅读:
    自定义Android Toasts风格
    用TAPI实现来电拒接
    压缩与解压缩的实现
    Android之个性化ListView实现
    如何在windows7 Home家庭版中创建Administrator管理员账户
    Android中Intent传递对象的两种方法(Serializable,Parcelable)
    Android模拟器入门
    上海西门子培训第六天(周五)
    上海西门子培训第七天(周六)
    计算机英语学习方法[摘录]
  • 原文地址:https://www.cnblogs.com/ppswaggy/p/13922390.html
Copyright © 2011-2022 走看看