Linux-5.0系统调用分析

学号:476
原创作品转载请注明出处
实验来源:https://github.com/mengning/linuxkernel/

一、实验要求
在这里插入图片描述
二、实验环境准备
1、编译Linux-5.0

1)下载Linux-5.0内核源码并解压;
2)cd linux-5.0 ; make menuconfig(可能缺少依赖bision和flex,按照提示安装即可)
在随后出现的图形化菜单界面中找到kernel hacking–>compile-time checks and compiler options—>选择compile the kernel with debug info;(为后面实验过程使用gdb调试作准备)

3)make bzImage;
在这里插入图片描述

2、制作根文件系统

cd ..
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu
gcc -pthread -o init linktable.c menu.c test.c -m32 -static
(这里可能出现64位编译32位程序出错的情况,执行了下面两条命令完成,根据自己的gcc版本安装一下库,我这里安装的是gcc-7...)
sudo apt-get install libc6-dev-i386
sudo apt install gcc-7 gcc-7-multilib g++-7 g++-7-multilib
接下来继续执行:
cd ../rootfs/
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

3、启动MenuOS

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd rootfs.img(根据自己是64位还是32位选择相应的qemu)

在这里插入图片描述
4、跟踪调试内核启动

qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd rootfs.img -S -s -append nokaslr
启动qemu之后,开一个新的终端:
cd linux-5.0
gdb vmlinux
(gdb)target remote:1234
(gdb)b start_kernel
(gdb)c

还是因为使用的是64位调试32位程序的原因会出现以下情况:
在这里插入图片描述
这里重新下载了gdb源码并安装还是出现类似问题,最终在网上找到解决方案,修改了gdb/remote.c的部分代码:

 if (buf_len > 2 * rsa->sizeof_g_packet)
     error (_(“Remote ‘g’ packet reply is too long: %s”), rs->buf);

  修改为:

  if (buf_len > 2 * rsa->sizeof_g_packet) {
      rsa->sizeof_g_packet = buf_len ;
      for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
      {
         if (rsa->regs[i].pnum == -1)
         continue;

         if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
         rsa->regs[i].in_g_packet = 0;
         else
         rsa->regs[i].in_g_packet = 1;
      }
   }


最终可以实现gdb调试代码:
在这里插入图片描述
三、实验内容
跟踪系统调用
学号后两位为76,vim /usr/include/asm/unistd_32.h 查看对应的系统调用函数是getrlimit,为获取系统资源上限函数。
在这里插入图片描述
该函数的调用形式为:

int getrlimit(int resource, struct rlimit *rptr);
如果成功则返回0,不成功返回非0,所以如果调用成功结果为0即可;
进程的资源是在系统初始化时由进程0建立的,然后由每个后续进程继承,每种实现都可以用自己的方法对各种限制做出调整。
这个函数的每一次调用都会制定一个资源以及一个指向下列结构的指针:
struct rlimit{
	rlim_t rlim_cur;   //soft limit: current limit
	rlim_t rlim_max;  //hard limit: maximum value for rlim_cur
}

函数的参数resource可以从以下值中取一个:

RLIMIT_AS:进程可用存储区的最大总长度(字节)。

RLIMIT_CORE:core文件的最大字节数,若取值为0则阻止创建core文件。

RLIMIT_CPU:CPU时间的最大值(秒),当超过此软限制时,向该进程发送SIGXCPU信号。

RLIMIT_DATA:数据段的最大字节长度。

RLIMIT_FSIZE:可以创建的文件的最大字节长度。当超过此软限制时,则向该进程发送SIGXFSZ信号。

RLIMIT_LOCKS:一个进程可持有的文件锁的最大数。

RLIMIT_MEMLOCK:一个进程使用mlock能够锁定在存储器中的最大字节长度。

RLIMIT_NOFILE:每个进程能打开最大文件数。更改此限制将影响到sysconf函数在参数_SC_OPEN_MAX返回的值。

RLIMIT_NPROC:每个实际用户ID可拥有的最大子进程数。更改此限制将影响到sysconf函数在参数_SC_CHILD_MAX返回的值。

RLIMIT_RSS:最大驻内存集的字节长度。(resident set size in bytes,RSS)

RLIMIT_SBSIZE:用户在任一给定时刻可以占用的套接字缓冲区的最大长度。

RLIMIT_STACK:栈的最大字节长度。

RLIMIT_VMEM:这是RLIMT_AS的同义词。

实验过程中只将resource的值确定为第一个RLIMIT_AS:进程可用存储区的最大总长度(字节)进行实验。
下面进入linux-5.0中的menu中,编辑test.c文件:
使用c语言调用API的方法代码:
在这里插入图片描述
使用c代码中嵌入汇编代码方式触发系统调用:
在这里插入图片描述

通过0x80执行中断进行系统调用,从eax寄存器获得返回值,eax传递系统调用号(76),ebx和ecx传递函数需要的参数。
在main函数中加入调用两个函数的命令:
在这里插入图片描述
最后按照之前的方式重新编译MenuOS:

gcc -pthread -o init linktable.c menu.c test.c -m32 -static
cd ../rootfs/
cp ../menu/init ./
find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd rootfs.img

运行结果如下所示,返回操作成功且得到进程资源上限大小:
在这里插入图片描述
查找sys.c文件的宏定义部分找到getrlimit函数的系统调用函数为old_prlimit(),如同实验开始准备实验环境时的方法一样,在该函数处打断点,可以用来分析系统调用函数的内核代码。
在这里插入图片描述

四、总结

  • 操作系统分为用户态和内核态,操作系统为用户态运行的进程和硬件之间进行交互提供了一组接口,通过调用这些接口函数向内核发出系统调用请求,由操作系统代为完成;

  • 在进入中断处理程序之前需要保护现场,也就是保存进程必须的寄存器,恢复现场就是将这些 实现系统调用首先需要使用int

  • $0x80汇编指令形成中断并且进行系统调用。这条汇编指令就是实现了从用户态到内核态的转换,将cpu的控制权交给系统调用处理函数system_call();

  • 首先将系统调用号和可能用到的寄存器保存在堆栈中,对用户态进程传递过来的系统调用号进行有效性检查,如果是合法的系统调用,根据eax中的系统调用号,内核进程查看系统调用表(sys_call_table),并且找到相应的服务例程。服务例程结束以后,从eax获得系统调用的返回值,并且把这个返回值存放在曾经保存用户态eax寄存器栈单元的那个位置上。跳转到ret_from_sys_call(),终止系统调用程序的执行。当进程恢复它在用户态的执行之前,RESTORE_ALL宏定义会恢复用户进入内核前被保存到堆栈中的寄存器的值。

首先,CNN-LSTM神经网络结构通常用于处理时间序列数据,其中CNN用于提取时间序列中的空间特征,LSTM用于处理时间序列中的时间依赖性。 对于多变量回归预测任务,我们可以采用以下步骤来实现CNN-LSTM神经网络: 1. 准备数据集:将多个变量的时间序列数据集合并成一个多维数组,其中每个维度表示一个变量,每个时间步表示一个样本。 2. 数据预处理:对数据进行归一化处理,使得每个变量的数值范围都在 [0,1] 之间。 3. 构建模型:使用PyTorch构建一个CNN-LSTM神经网络模型,其中CNN部分使用卷积层提取空间特征,LSTM部分处理时间序列数据,最后输出多个变量的预测结果。 4. 训练模型:使用训练集对模型进行训练,采用均方误差(MSE)作为损失函数。 5. 测试模型:使用测试集对模型进行测试,计算均方误差和平均绝对误差(MAE)等指标来评估模型性能。 下面是一个简单的CNN-LSTM神经网络实现的示例代码: ```python import torch import torch.nn as nn import torch.optim as optim import numpy as np # 构建CNN-LSTM神经网络模型 class CNNLSTM(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(CNNLSTM, self).__init__() self.hidden_size = hidden_size self.conv1 = nn.Conv2d(1, 32, kernel_size=(3, 3), padding=(1, 1)) self.conv2 = nn.Conv2d(32, 64, kernel_size=(3, 3), padding=(1, 1)) self.pool = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2)) self.lstm = nn.LSTM(input_size, hidden_size) self.fc = nn.Linear(hidden_size, output_size) def forward(self, x): x = self.conv1(x) x = nn.functional.relu(x) x = self.pool(x) x = self.conv2(x) x = nn.functional.relu(x) x = self.pool(x) x = x.permute(3, 0, 1, 2) _, (h, _) = self.lstm(x) h = h.squeeze() out = self.fc(h) return out # 准备数据集 data = np.random.rand(100, 5, 10) # 100个样本,5个变量,每个变量10个时间步 target = np.random.rand(100, 3) # 100个样本,3个变量的预测结果 # 数据预处理 data = (data - np.min(data)) / (np.max(data) - np.min(data)) target = (target - np.min(target)) / (np.max(target) - np.min(target)) # 转换为PyTorch张量 data = torch.from_numpy(data).float() target = torch.from_numpy(target).float() # 定义模型和优化器 model = CNNLSTM(5, 64, 3) optimizer = optim.Adam(model.parameters(), lr=0.001) criterion = nn.MSELoss() # 训练模型 for epoch in range(100): optimizer.zero_grad() output = model(data.unsqueeze(1)) loss = criterion(output.squeeze(), target) loss.backward() optimizer.step() if epoch % 10 == 0: print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, 100, loss.item())) # 测试模型 with torch.no_grad(): test_data = np.random.rand(10, 5, 10) # 10个测试样本 test_data = (test_data - np.min(test_data)) / (np.max(test_data) - np.min(test_data)) test_data = torch.from_numpy(test_data).float() test_output = model(test_data.unsqueeze(1)) print('Test Output: ', test_output.squeeze().numpy()) ``` 在上述代码中,首先定义了一个CNNLSTM类作为CNN-LSTM神经网络模型。模型包括两个部分:CNN部分和LSTM部分。CNN部分使用两个卷积层和一个最大池化层提取空间特征,LSTM部分处理时间序列数据。最后,使用一个全连接层输出多个变量的预测结果。 然后,我们准备了一个随机的多变量时间序列数据集,并将其归一化处理。接着,我们定义了一个Adam优化器和一个均方误差损失函数,并使用训练集对模型进行训练。 最后,我们使用测试集对模型进行测试,并计算均方误差和平均绝对误差等指标来评估模型性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值