Linux内核分析(四)

时间:2019-09-25
本文章向大家介绍Linux内核分析(四),主要包括Linux内核分析(四)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

开始

用两种方式实现使用同一个系统调用:

  • 库函数API
  • C代码中内嵌汇编

本实验目的是为了熟悉Linux系统调用的相关知识,以及熟悉Linux和嵌入式汇编的写法。

实验内容

选择一个系统调用,列表见这里,我们选择write系统调用。
用C写一个文件test.c,代码如下:

1
2
3
4
5
6
7

#include <unistd.h>
int (void)
{
write(1,"hello world!n",13);
return 0;
}

这里,write函数有三个参数,第一个表示写到终端屏幕上,1可以认为是屏幕的代号,第二个参数是写的内容,第三个参数是写入字符串的长度。
运行结果如下图所示:

然后需要把这段代码转化为嵌入式汇编的格式,嵌入式汇编的格式如下:

在test_asm.c中,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
#include<unistd.h>

int (void)
{
int a;
char *ch="hello world!n";

__asm__(
"movl $0x4,%%eaxnt"
"movl $0x1,%%ebxnt"//ebx传递参数,第一个参数1
"movl %1,%%ecxnt"//ecx存储输出位置,第二个参数字符串ch
"movl $0xd,%%edxnt"//edx存储参数长度,第三个参数13
"int $0x80nt"//执行系统调用
"movl %%eax,%0nt"//系统调用返回值存入eax
:"=m"(a)//输出
:"c"(ch)//输入
);
return 0;
}

执行结果如下所示:

这里代码:

1
"movl %1,%%ecxnt"//ecx存储输出位置

中的%1,表示传递的第一个参数,它和后面的输入:

1
:"c"(ch)//输入

是相呼应的,c表示ecx,表示把字符串a存入ecx中。
而其他的代码:

1
"movl $0x1,%%ebxnt"//ebx传递参数

$0x1表示把立即数1存入ebx中,也是作为参数的。按照顺序传递参数。

总结

系统调用的三个层次如下所示:

分别为:xyz函数(API)、system call(中断向量)和 sys xyz(中断服务程序)。

当用户进程需要发生系统调用时,CPU 通过软中断切换到内核态开始执行内核系统调用函数。Linux 下有三种发生系统调用的方法:

  1. 通过 glibc 提供的库函数
  2. 使用 syscall 函数直接调用
  3. 通过 int 0x80指令陷入

总的来说,前两种最终都会通过int 0x80指令陷入进入中断处理程序。而系统调用也需要输入输出参数,例如实际的值,用户态进程地址空间的变量的地址,甚至是包含指向用户态函数的指针的数据结构的地址等。
system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,即由eax传递的系统调用号,其他参数依次由ebx,ecx,edx,esi,edi,ebp传入。
寄存器传递参数具有如下限制:

  1. 每个参数的长度不能超过寄存器的长度,即32位
  2. 在系统调用号(eax)之外,参数的个数不能超过6个(ebx,ecx,edx,esi,edi,ebp)

【版权声明】
本文首发于戚名钰的博客,欢迎转载,但是必须保留本文的署名戚名钰(包含链接)。如您有任何商业合作或者授权方面的协商,请给我留言:qimingyu.security@foxmail.com
欢迎关注我的微信公众号:科技锐新

本文永久链接:http://qimingyu.github.io/2016/04/08/Linux内核分析(四)/

原文:大专栏  Linux内核分析(四)


原文地址:https://www.cnblogs.com/petewell/p/11585206.html