(2023-2024-1)20232830《Linux内核原理分析与设计》第五周作业
1. 《庖丁解牛Linux分析》第5章
进程的通信与创建
2. 实验四:两种不同方式的系统调用
本次实验为分别使用库函数和C语言嵌入汇编代码的方式对系统进行同一个调用,所选择的是116号系统调用sysinfo。
2.1 库函数调用
使用库函数调用sysinfo,代码sysinfo.c如下:
#include<stdio.h>
#include<linux/kernel.h> // 包含 struct sysinfo 消息结构
void main() {
struct sysinfo si; // 定义 sysinfo 结构体变量 si
int result;
result = sysinfo(&si); // 调用 sysinfo() 函数获取系统信息,并将结果存储在 si 变量中
printf("result=%d\n", result); // 打印获取系统信息的结果,即 sysinfo() 函数的返回值
printf("total memory=%ld\n", si.totalram); // 打印系统总内存量,以字节为单位
printf("free memory=%ld\n", si.freeram); // 打印系统空闲内存量,以字节为单位
}
这段代码使用了 <stdio.h> 头文件中的 printf() 函数和 <linux/kernel.h> 头文件中的 struct sysinfo 结构体和 sysinfo() 函数。
- struct sysinfo 是 Linux 内核提供的一个结构体,用于存储系统的各种信息,如内存使用情况、负载情况等。
- sysinfo() 函数是一个系统调用,用于获取系统的详细信息,包括内存使用情况等,并将结果存储在传入的 struct sysinfo 变量中。
代码中的主要逻辑如下:
- 定义了一个名为 si 的 struct sysinfo 类型的变量,用于存储系统信息。
- 调用 sysinfo() 函数,将系统信息存储在 si 变量中,并将返回值赋给 result 变量。
- 使用 printf() 函数打印获取到的系统信息,包括 result(sysinfo() 的返回值)、系统总内存量(si.totalram)和系统空闲内存量(si.freeram)。
2.2 C语言内联汇编调用
使用C语言内联汇编调用sysinfo,代码sysinfoc.c如下:
#include<stdio.h>
#include<linux/kernel.h>
int main() {
struct sysinfo si; // 定义 sysinfo 结构体变量 si
int result = 100; // 初始化 result 变量为 100
unsigned long totalram = 0; // 初始化 totalram 变量为 0
unsigned long freeram = 0; // 初始化 freeram 变量为 0
asm volatile(
"mov $116,%%eax\n\t" // 将系统调用号 116(sysinfo)加载到寄存器 eax 中
"mov %1,%%ebx\n\t" // 将 si 结构体变量的地址加载到寄存器 ebx 中
"int $0x80\n\t" // 执行中断指令,触发系统调用
"mov %%eax,%0\n\t" // 将系统调用的返回值存储到 result 变量中
:"=r"(result) // 输出约束:将结果存储到 result 变量中
:"b"(&si) // 输入约束:将 si 结构体变量的地址传递给 ebx 寄存器
: // 无需使用的寄存器
);
printf("result=%d\n", result); // 打印系统调用的返回值
printf("total memory=%ld\n", si.totalram); // 打印系统总内存量,以字节为单位
printf("free memory=%ld\n", si.freeram); // 打印系统空闲内存量,以字节为单位
return 0;
}
这段代码主要逻辑如下:
- 定义了一个名为 si 的 struct sysinfo 类型的变量,用于存储系统信息。
- 初始化了 result、totalram 和 freeram 变量,分别为 100、0 和 0。
- 使用内联汇编(Inline Assembly)的方式调用 Linux 内核的系统调用,具体为系统调用号 116(sysinfo)。
- 使用汇编指令将系统调用号加载到 eax 寄存器中。
- 使用汇编指令将 si 结构体变量的地址加载到 ebx 寄存器中。
- 执行中断指令触发系统调用。
- 将系统调用的返回值存储到 result 变量中。
- 使用 printf() 函数打印获取到的系统信息,包括 result(系统调用的返回值)、系统总内存量(si.totalram)和系统空闲内存量(si.freeram)。
- 返回 0 表示程序运行成功。
2.3 运行结果
分别对两个文件进行编译并运行,结果如下:
3. 总结
库函数调用和内联汇编调用区别如下:
- 抽象级别:库函数调用是高级语言中使用函数调用触发系统调用,无需了解底层细节;内联汇编调用直接使用汇编指令触发系统调用,需要了解汇编语言和系统调用的细节。
- 可移植性:库函数调用具有较好的可移植性,可以在不同平台上编译和运行;内联汇编调用的可移植性较差,特定于底层硬件和操作系统。
- 简洁性和可读性:库函数调用使代码更简洁和易读;内联汇编调用使代码变得冗长和难以理解。
- 性能:内联汇编调用系统调用通常具有较好的性能,绕过了库函数调用的开销。