内核编程 1. 添加一个系统调用, 该系统调用接受两个参数:参数1:以整型数表示的自己学号的后3位;参数2:flag,取值为0或1,若为0,该系统调用的返回值为参数1的个位。若为1。该系统调用的返回值为参数1的十位。 2. 对上面的系统调用进行修改,修改如下: i. 声明一个内核全局变量gOSE, 该系统首先将参数1的值赋给gOSE,并且,对于参数2:flag,取值为0或1,若为0,将gOSE的值按位取反,后赋值给gOSE,然后返回gOSE的值;若为1,则将gOSE的值与0Xffffffff异或,后赋值给gOSE,然后返回gOSE的值; ii. 加入内核互斥锁,使得两个进程在调用该系统调用时,能够做到互斥访问gOSE。 2. 对于系统调用编程题中的strict alternation算法,给出该算法中turn变量的虚地址,并且给出该变量的物理地址。 请提交代码截图和运行结果截图
时间: 2023-12-30 09:04:10 浏览: 23
抱歉,由于我是一个语言模型AI,无法为您提供代码截图和运行结果截图。但是,我可以为您提供一些帮助和指导。
1. 添加系统调用
在 Linux 内核中添加系统调用需要修改内核源代码,具体步骤如下:
1. 打开内核源代码文件 `include/linux/syscalls.h` ,添加以下内容:
```
asmlinkage long sys_my_syscall(int num, int flag);
```
2. 打开内核源代码文件 `arch/x86/entry/syscalls/syscall_64.tbl` ,在文件末尾添加以下内容:
```
333 common my_syscall sys_my_syscall
```
3. 打开内核源代码文件 `kernel/sys.c` ,在文件末尾添加以下内容:
```
asmlinkage long sys_my_syscall(int num, int flag)
{
int ret;
if (flag == 0) {
ret = num % 10;
} else if (flag == 1) {
ret = (num / 10) % 10;
} else {
ret = -EINVAL; // 如果 flag 不为 0 或 1,则返回错误码 -EINVAL
}
return ret;
}
```
4. 重新编译内核,并安装新内核。
2. 修改系统调用
在上面的系统调用的基础上,我们需要添加一个内核全局变量 `gOSE` 和一个内核互斥锁。具体步骤如下:
1. 打开内核源代码文件 `include/linux/syscalls.h` ,修改以下内容:
```
extern int gOSE;
asmlinkage long sys_my_syscall(int num, int flag);
```
2. 打开内核源代码文件 `kernel/sys.c` ,在文件末尾添加以下内容:
```
DEFINE_MUTEX(my_mutex);
int gOSE;
asmlinkage long sys_my_syscall(int num, int flag)
{
int ret;
mutex_lock(&my_mutex);
gOSE = num;
if (flag == 0) {
gOSE = ~gOSE;
} else if (flag == 1) {
gOSE = gOSE ^ 0xffffffff;
} else {
mutex_unlock(&my_mutex); // 如果 flag 不为 0 或 1,则返回错误码 -EINVAL 并解锁互斥锁
return -EINVAL;
}
ret = gOSE;
mutex_unlock(&my_mutex);
return ret;
}
```
3. 重新编译内核,并安装新内核。
3. strict alternation算法
在临界区中使用 strict alternation 算法需要使用一个共享变量 `turn`,并且需要使用 volatile 变量类型来保证编译器不会对该变量进行优化。具体实现如下:
```
volatile int turn = 0;
void process1()
{
while (true) {
while (turn != 0);
// 进入临界区
// ...
// 离开临界区
turn = 1;
}
}
void process2()
{
while (true) {
while (turn != 1);
// 进入临界区
// ...
// 离开临界区
turn = 0;
}
}
```
在上面的代码中,`turn` 变量的虚地址为 `&turn`,而其物理地址则需要通过查看系统内存映射表来确定。运行结果截图也需要根据具体实现情况来确定。