2019-2020-1 20,199,321 작품의 다섯 번째 주에 "리눅스 커널 원리 및 분석"

첫 번째 부분 노트

内核态:高执行级别,代码可以执行特权指令,访问任意的物理内存,CPU的执行级别对应的就是内核态。
用户态:与内核态相对应的低级别指令,代码能够掌控的范围会受到限制。

Intel x86 CPU有四种不同的执行级别,分别是0,1,2,3其中数字越小,特权越高。Linux操作系统只采用了其中的0和3两个特权级别,分别对 应内核态和用户态.用户态和内核态很显著的区别方法就是CS:EIP的指向范围,内核态CS:EIP的值是任意的,即可以访问所有的地址空间。 用户态只能访问其中的一部分内存地址(0x00000000-0xbbbbbbbf),0xc0000000以上的地址只能在内核态下访问。
CS:代码段选择寄存器  EIP:偏移量寄存器。

中断:由中断触发进入内核态。硬件中断或是由调用系统调用(Trap)引起中断,陷入内核态。从用户态切换到内核态,将用户态寄存器的上下文保存起来,同时将内核态寄存器的值放入当前CPU中。
系统调用的特点:把用户从底层的硬件编程中解放出来;极大的提高了系统的安全性;使用户程序具有可移植性。

系统调用的库函数就是我们使用的操作系统提供的API,系统调用是通过软中断向内核发出中断请求,int指令的执行中触发断请求。
libc函数库内部定义的一些API内部就使用了系统调用的封装历程。每个系统调用对应一个系统调用的封装例程。

  • 사용자 모드는 커널 모드는 커널 모드를 나타내며, 사용자 모드를 나타냅니다. XYZ () API 함수는 다음 ret_from_sys_call 내부 sys_xyz () 시스템 호출 핸들러가있을 것, 즉 0x80으로 인터럽트 벡터 인터럽트 서비스 루틴 항목을 해당하고, () 중단 시작 system_call 커널 코드에 대응 INT $ 0x80으로 트리거된다.
  • 3 층 시스템 호출기구 : XYZ (); system_call; sys_xyz ().
  • 시스템 전화 번호 : 커널이 각 시스템에 번호를 호출하여 구분합니다. 이 API 함수 XYZ () 시스템 호출 및 커널 함수 sys_xyz () 연결합니다.
  • 사용자 프로세스는 EAX 레지스터 전송을 매개 변수의 명명 된 시스템 호출 번호를 사용하여 시스템 호출을 필요로하는 지정해야합니다.
  • 사용자 모드에서 커널 모드로 전환 할 때 사용되는 다른 스택 시스템 호출, 송신 파라미터는 파라미터의 가압에 의해 전달 될 수 없다. 여섯 개 레지스터를 초과 할 수 EBX ECX EDX ESI EDI의 EBP 오더 파라미터에 할당 된 파라미터의 수. 매개 변수가 너무 큰 경우, 포인터로 레지스터는 이상의 매개 변수를 전달하기 위해 메모리를 넣어.

실험의 두 번째 부분

  • 라이브러리 함수 시스템 호출 API를 사용하여
#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:\n",t->tm_year+1900,t->tm_mon,t->tm_mda,t->tm_hour,t->tm_min,t->tm_sec);
 return 0;
}

  • 어셈블러 코드 임베디드 시스템 호출에서 C 코드
#include<stdio.h>
#include<time.h>
int main()
{
 time_t tt;
 struct tm *t;
 asm volatile
 (
    "mov $0,%%ebx\n\t"//把EBX寄存器清0
    "mov $0xd,%%eax\n\t"//eax用于传递系统调用号
    "int $0x80\n\t"//触发系统调用陷入内核执行13好系统调用的内核处理函数
    "mov %%eax,%0\n\t"//系统调用的返回值通过eax返回
    :"=m"(tt)
  );
 t=localtime(&tt);
 printf("time:%d:%d:%d:%d:%d:%d:\n",t->tm_year+1900,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
 return 0;
 }
    

  • 이 방법은 트리거 시스템은 -38를 호출 있습니다


  • 유니버설 트리거 시스템 콜을 호출
#include<stdio.h>
#include<sys/syscall.h>
int main()
{
 int ret;
 char oldname[]="hello.c";
 char newname[]="newhello.c";
 ret=syscall(38,oldname,newname);
 if (ret==0)
    printf("Renamed successfully\n");
else
    printf("Unable to renam the file\n");
 return 0;
 }


libc의이 포장 시스템 호출을 제공하지 않는다, 콜은 직접 함수는 libc의 호출을 제공하는 데에 이용 될 수있다

추천

출처www.cnblogs.com/20199321zjy/p/11686847.html