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),从而返回主程序继续运行。

  • 相关阅读:
    Leetcode Unique Binary Search Trees
    Leetcode Decode Ways
    Leetcode Range Sum Query 2D
    Leetcode Range Sum Query
    Leetcode Swap Nodes in Pairs
    Leetcode Rotate Image
    Leetcode Game of Life
    Leetcode Set Matrix Zeroes
    Leetcode Linked List Cycle II
    CF1321A
  • 原文地址:https://www.cnblogs.com/ppswaggy/p/13922390.html
Copyright © 2011-2022 走看看