【OS】实验三:进程管理

899 阅读2分钟

实验三:进程管理

任务1:创建并运行内核线程

编写kthread.c和Makefile文件 kthread.c

#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/delay.h>
MODULE_LICENSE("GPL");
#define BUF_SIZE 20
static struct task_struct *myThread = NULL;
static int print(void *data)
{
    while(!kthread_should_stop()){
        printk("New kthread is running.");
        msleep(2000);
    }
    return 0;
}
static int __init kthread_init(void)
{
    printk("Create kernel thread!\n");
    myThread = kthread_run(print, NULL, "new_kthread");
    return 0;
}
static void __exit kthread_exit(void)
{
    printk("Kill new kthread.\n");if(myThread)
        kthread_stop(myThread);
}
module_init(kthread_init);
module_exit(kthread_exit);

Makefile

ifneq ($(KERNELRELEASE),)
    obj-m := kthread.o
else
    KERNELDIR ?= /root/kernel-5.10.0-13.0.0
    PWD := $(shell pwd)
default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
.PHONY:clean
clean:
    -rm *.mod.c *.o *.order *.symvers *.ko

执行make以及模块加载:

image-20211224231031602

卸载模块:

image-20211224231119072

任务2:打印输出当前系统 CPU 负载情况

编写cpu_loadavg.c:

#include <linux/module.h>
#include <linux/fs.h>

MODULE_LICENSE("GPL");

char tmp_cpu_load[5] = {'\0'};

static int get_loadavg(void)
{
	struct file *fp_cpu;
	loff_t pos = 0;
	char buf_cpu[10];
	fp_cpu = filp_open("/proc/loadavg", O_RDONLY, 0);
	if (IS_ERR(fp_cpu)){
		printk("Failed to open loadavg file!\n");
		return -1;
	}
	kernel_read(fp_cpu, buf_cpu, sizeof(buf_cpu), &pos);
	strncpy(tmp_cpu_load, buf_cpu, 4);
	filp_close(fp_cpu, NULL);
	return 0;
}

static int __init cpu_loadavg_init(void)
{
	printk("Start cpu_loadavg!\n");
	if(0 != get_loadavg()){
		printk("Failed to read loadarvg file!\n");
		return -1;
	}
	printk("The cpu loadavg in one minute is: %s\n", tmp_cpu_load);
	return 0;
}

static void __exit cpu_loadavg_exit(void)
{
	printk("Exit cpu_loadavg!\n");
}

module_init(cpu_loadavg_init);
module_exit(cpu_loadavg_exit);

Makefile

ifneq ($(KERNELRELEASE),)
	obj-m := cpu_loadavg.o
else
	KERNELDIR ?= /root/kernel-5.10.0-13.0.0
	PWD := $(shell pwd)
default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
.PHONY:clean
clean:
	-rm *.mod.c *.o *.order *.symvers *.ko

内核模块加载结果

image-20211224231840841

任务3:打印输出当前处于运行状态的进程的 PID 和名字

process_info.c

#include <linux/module.h>
#include <linux/sched/signal.h>
#include <linux/sched.h>

MODULE_LICENSE("GPL");

struct task_struct *p;

static int __init process_info_init(void)
{
	printk("Start process_info!\n");
	for_each_process(p){
		if(p->state == 0)
			printk("1)name:%s  2)pid:%d  3)state:%ld\n", p->comm, p->pid, p->state);
	}
	return 0;
}

static void __exit process_info_exit(void)
{
	printk("Exit process_info!\n");
}

module_init(process_info_init);
module_exit(process_info_exit); 

Makefile

ifneq ($(KERNELRELEASE),)
	obj-m := process_info.o
else
	KERNELDIR ?= /root/kernel-5.10.0-13.0.0
	PWD := $(shell pwd)
default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
.PHONY:clean
clean:
	-rm *.mod.c *.o *.order *.symvers *.ko

内核模块加载结果

image-20211225153210095

任务4:使用 cgroup 实现限制 CPU 核数

1、挂载tmpfs格式的cgroup文件夹

在root权限执行以下命令:

mkdir /cgroup
mount -t tmpfs tmpfs /cgroup
cd /cgroup  

挂载tmpfs文件类型:tmpfs是直接建立在VM之上的,用一个简单的mount命令就可以创建tmpfs文件系统了。速度快,可以动态分配文件系统大小。

image-20211225154014288

2、挂载cpuset管理子系统

挂载某一个 cgroups 子系统到挂载点之后,就可以通过在挂载点下面建立文件夹或者使用cgcreate命令的方法创建 cgroups 层级结构中的节点/控制组;对应的删除则使用 rmdir删除文件夹,或使用cgdelete命令删除。

mkdir cpuset
mount -t cgroup -o cpuset cpuset /cgroup/cpuset  #挂载cpuset子系统
cd cpuset
mkdir mycpuset   #创建一个控制组,删除用 rmdir 命令
cd mycpuset  

3、设置cpu核数

echo 0 > cpuset.mems #设置0号内存结点。mems默认为空,因此需要填入值。
echo 0-2 > cpuset.cpus  #这里的0-2指的是使用cpu的0、1、2三个核。实现了只是用这三个核。

image-20211225154455723

image-20211225154538651

4、简单的死循环C源文件while_long.c

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	while (1){}
	printf("Over");
	exit(0);
}

5、测试验证

(1)打开一个终端,执行以下命令:

## 编译上述C源文件
gcc while_long.c -o while_long
##  指定在cpuset子系统的mycpuset控制组中运行while_long,使用 ctrl+c 退出运行
cgexec -g cpuset:mycpuset ./while_long  

执行如下:

image-20211225160349932

(2)不要关闭上述终端,另打开一个终端,执行以下命令:

top   #查看程序while_long的PID, 假设为4064。输入q 退出当前查看状态
taskset -p 4064 # 显示的如果是7(111),则测试限制cpu核数成功。  

执行如下:

image-20211225160722353

遇到问题

cgexec: command not found

需对libcgroup进行安装

image-20211225160256719