1、创建并运行内核线程
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()){//接收kthread_stop传递的结束线程信号,如果内核线程中未用此函数,则kthread_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);//发送信号给myThread指向的线程,使之退出
}
module_init(kthread_init);
module_exit(kthread_exit);
编译运行:
分析运行结果,加载模块后,执行 kthread_run(print, NULL, "new_kthread"),成功创建并启动了内核线程,然后一直在运行,当卸载掉该模块后,调用 kthread_stop(myThread),退出线程。
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);
编译运行:
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);
编译运行:
成功打印出了当前运行态的:
-
进程名:insmod
-
进程ID:7166
-
状态:0
4、使用 cgroup 实现限制 CPU 核数
1、挂载tmpfs格式的cgroup文件夹
2、挂载cpuset管理子系统
3、设置cpu核数(设置0号内存结点,只使用cpu的0、1、2核。)
4、while_long.c:(实现死循环,持续运行,最后使用快捷键Ctrl+z结束)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
while (1){}
printf("Over");
exit(0);
}
5、验证
(1)编译上面的c程序,指定在cpuset子系统的mycpuset控制组中运行while_long。
首先安装cgroup:
yum install libcgroup
(2)使用top命令得到while_long的进程id为7899:
5、使用 cgroup 实现不允许访问U盘
在该实验中,需要注意U盘接口类型是否被虚拟机支持,以及U盘的文件系统类型(NTFS、exFAT或FAT32等等),在此使用NTFS格式的U盘,openEuler系统无法识别,随后在Windows中格式化U盘、修改其格式为FAT32,成功完成了后续实验。
插入U盘,在虚拟机中设置USB设备:
查看U盘盘符:
最后一行/dev/sdb1为U盘。
获取设备号(设备号为8,16):
挂载U盘、挂载devices子系统,并设置U盘拒绝访问:
报错,不支持文件系统,将U盘修改为FAT32格式并继续:
验证:
设置参数使得禁止访问该U盘:
成功,弹出不允许打开U盘的提示。