Linux驱动学习——进程管理
背景
关于进程管理的介绍参考Linux内核学习——进程管理
内核线程
- 编写一个内核模块,创建一组内核线程,每个CPU一个内核线程
- 在每个内核线程中,打印当前CPU的状态
- 在每个内核线程中,打印当前进程的优先级等信息
代码
kthread.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>
// 指定license版本
MODULE_LICENSE("GPL");
// 作者信息
MODULE_AUTHOR("Marvin");
// 模块描述
MODULE_DESCRIPTION("process kthread demo");
// 提供别名
MODULE_ALIAS("processkthread");
static struct task_struct *tsk[NR_CPUS];
static void show_prio(void)
{
struct task_struct *task = current;
printk("%s pid:%d, nice:%d prio:%d static_prio:%d normal_prio:%d\n",
task->comm, task->pid,
PRIO_TO_NICE(task->static_prio),
task->prio, task->static_prio,
task->normal_prio);
}
static void print_cpu(char *s)
{
preempt_disable();
pr_info("%s cpu=%d.\n", s, smp_processor_id());
preempt_enable();
}
static int thread_fun(void *t)
{
do {
print_cpu("SLEEP in Thread Function ");
msleep_interruptible(2000);
print_cpu("msleep over in Thread Function");
print_cpu("running");
show_prio();
} while (!kthread_should_stop());
return 0;
}
static int __init my_init(void)
{
int i;
print_cpu("Loading module");
for_each_online_cpu(i) {
tsk[i] = kthread_create(thread_fun, NULL, "kdemo/%d", i);
if (!tsk[i]) {
pr_info("Failed to generate a kernel thread\n");
return -1;
}
kthread_bind(tsk[i], i);
pr_info("About to wake up and run the thread for cpu=%d\n", i);
wake_up_process(tsk[i]);
pr_info("Staring thread for cpu %d", i);
print_cpu("on");
}
return 0;
}
static void __exit my_exit(void)
{
int i;
for_each_online_cpu(i) {
pr_info(" Kill Thread %d", i);
kthread_stop(tsk[i]);
print_cpu("Kill was done on ");
}
pr_info("goodbye\n");
}
module_init(my_init);
module_exit(my_exit);
测试
sudo insmod processkthread.ko
sudo rmmod processkthread.ko
内核日志
[ 2553.129572] Loading module cpu=2.
[ 2553.129676] About to wake up and run the thread for cpu=0
[ 2553.129680] Staring thread for cpu 0
[ 2553.129681] on cpu=2.
[ 2553.129717] About to wake up and run the thread for cpu=1
[ 2553.129720] Staring thread for cpu 1
[ 2553.129721] on cpu=2.
[ 2553.129721] SLEEP in Thread Function cpu=0.
[ 2553.129723] SLEEP in Thread Function cpu=1.
[ 2553.129745] About to wake up and run the thread for cpu=2
[ 2553.129747] Staring thread for cpu 2
[ 2553.129748] on cpu=2.
[ 2553.129753] SLEEP in Thread Function cpu=2.
[ 2553.129774] About to wake up and run the thread for cpu=3
[ 2553.129777] Staring thread for cpu 3
[ 2553.129778] on cpu=2.
[ 2553.129779] SLEEP in Thread Function cpu=3.
[ 2555.136273] msleep over in Thread Function cpu=1.
[ 2555.136273] msleep over in Thread Function cpu=2.
[ 2555.136276] running cpu=1.
[ 2555.136277] running cpu=2.
[ 2555.136277] kdemo/1 pid:3390, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2555.136278] kdemo/2 pid:3391, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2555.136279] SLEEP in Thread Function cpu=1.
[ 2555.136279] SLEEP in Thread Function cpu=2.
[ 2555.136281] msleep over in Thread Function cpu=3.
[ 2555.136283] running cpu=3.
[ 2555.136283] kdemo/3 pid:3392, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2555.136284] SLEEP in Thread Function cpu=3.
[ 2555.136286] msleep over in Thread Function cpu=0.
[ 2555.136288] running cpu=0.
[ 2555.136289] kdemo/0 pid:3389, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2555.136290] SLEEP in Thread Function cpu=0.
[ 2557.184343] msleep over in Thread Function cpu=1.
[ 2557.184343] msleep over in Thread Function cpu=2.
[ 2557.184344] msleep over in Thread Function cpu=3.
[ 2557.184346] running cpu=3.
[ 2557.184346] running cpu=2.
[ 2557.184347] kdemo/3 pid:3392, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2557.184347] running cpu=1.
[ 2557.184347] kdemo/2 pid:3391, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2557.184349] SLEEP in Thread Function cpu=2.
[ 2557.184348] kdemo/1 pid:3390, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2557.184349] SLEEP in Thread Function cpu=3.
[ 2557.184350] SLEEP in Thread Function cpu=1.
[ 2557.184389] msleep over in Thread Function cpu=0.
[ 2557.184390] running cpu=0.
[ 2557.184391] kdemo/0 pid:3389, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2557.184392] SLEEP in Thread Function cpu=0.
[ 2559.232335] msleep over in Thread Function cpu=0.
[ 2559.232335] msleep over in Thread Function cpu=2.
[ 2559.232335] msleep over in Thread Function cpu=1.
[ 2559.232346] running cpu=0.
[ 2559.232346] running cpu=2.
[ 2559.232346] kdemo/0 pid:3389, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2559.232347] running cpu=1.
[ 2559.232347] kdemo/2 pid:3391, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2559.232348] SLEEP in Thread Function cpu=0.
[ 2559.232347] msleep over in Thread Function cpu=3.
[ 2559.232348] kdemo/1 pid:3390, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2559.232349] running cpu=3.
[ 2559.232349] SLEEP in Thread Function cpu=2.
[ 2559.232350] kdemo/3 pid:3392, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2559.232350] SLEEP in Thread Function cpu=1.
[ 2559.232351] SLEEP in Thread Function cpu=3.
[ 2561.245601] Kill Thread 0
[ 2561.245653] msleep over in Thread Function cpu=0.
[ 2561.245656] running cpu=0.
[ 2561.245656] kdemo/0 pid:3389, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2561.245665] Kill was done on cpu=1.
[ 2561.245666] Kill Thread 1
[ 2561.245670] msleep over in Thread Function cpu=1.
[ 2561.245671] running cpu=1.
[ 2561.245671] kdemo/1 pid:3390, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2561.245676] Kill was done on cpu=1.
[ 2561.245677] Kill Thread 2
[ 2561.245718] msleep over in Thread Function cpu=2.
[ 2561.245720] running cpu=2.
[ 2561.245720] kdemo/2 pid:3391, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2561.245728] Kill was done on cpu=1.
[ 2561.245729] Kill Thread 3
[ 2561.245774] msleep over in Thread Function cpu=3.
[ 2561.245776] running cpu=3.
[ 2561.245776] kdemo/3 pid:3392, nice:0 prio:120 static_prio:120 normal_prio:120
[ 2561.245784] Kill was done on cpu=1.
[ 2561.245785] goodbye
同时可以在命令行中查看:
$ ps -ef | grep kdemo
root 2294 2 0 11:36 ? 00:00:00 [kdemo/0]
root 2295 2 0 11:36 ? 00:00:00 [kdemo/1]
root 2296 2 0 11:36 ? 00:00:00 [kdemo/2]
root 2297 2 0 11:36 ? 00:00:00 [kdemo/3]
后台守护进程
使用daemon函数,创建一个守护进程
代码
daemon.c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/klog.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#define FALLBACK_KLOG_BUF_SHIFT 17 /* CONFIG_LOG_BUF_SHIFT in kernel */
#define FALLBACK_KLOG_BUF_LEN (1 << FALLBACK_KLOG_BUF_SHIFT)
#define KLOG_CLOSE 0
#define KLOG_OPEN 1
#define KLOG_READ 2
#define KLOG_READ_ALL 3
#define KLOG_READ_CLEAR 4
#define KLOG_CLEAR 5
#define KLOG_CONSOLE_OFF 6
#define KLOG_CONSOLE_ON 7
#define KLOG_CONSOLE_LEVEL 8
#define KLOG_SIZE_UNREAD 9
#define KLOG_SIZE_BUFFER 10
/* we use 'Linux version' string instead of Oops in this lab */
// #define OOPS_LOG "Oops"
#define OOPS_LOG "Linux version"
int save_kernel_log(char *buffer) {
char path[128];
time_t t;
struct tm *tm;
int fd;
t = time(0);
tm = localtime(&t);
snprintf(path, 128, "/tmp/%d.%d.%d.%d.%d.%d.log", tm->tm_year + 1900,
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
printf("%s\n", path);
fd = open(path, O_WRONLY | O_CREAT, 0644);
if (fd == -1) {
printf("open error\n");
return -1;
}
write(fd, buffer, strlen(buffer));
close(fd);
return 0;
}
int check_kernel_log() {
char *buffer;
char *p;
ssize_t klog_size;
int ret = -1;
int size;
printf("start kernel log\n");
klog_size = klogctl(KLOG_SIZE_BUFFER, 0, 0);
if (klog_size <= 0) {
klog_size = FALLBACK_KLOG_BUF_LEN;
}
printf("kernel log size: %d\n", klog_size);
buffer = malloc(klog_size + 1);
if (!buffer)
return -1;
size = klogctl(KLOG_READ_ALL, buffer, klog_size);
if (size < 0) {
printf("klogctl read error\n");
goto done;
}
buffer[size] = '\0';
/* check if oops in klog */
p = strstr(buffer, OOPS_LOG);
if (p) {
printf("we found '%s' on kernel log\n", OOPS_LOG);
save_kernel_log(buffer);
ret = 0;
}
done:
free(buffer);
return ret;
}
int main(void) {
if (daemon(0, 0) == -1) {
printf("daemon error");
return 0;
}
while (1) {
check_kernel_log();
sleep(5);
}
return 0;
}
测试
gcc daemon.c -o daemon
sudo ./daemon
会在指定的目录下每5s转存下内核日志。
进程权限
编写一个用户程序,限制该程序的一些资源,比如进程的最大虚拟内存空间等。
代码
resource_limit.c
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <errno.h>
#define DEATH(mess) { perror(mess); exit(errno); }
void do_limit(int limit, const char *limit_string, struct rlimit *rlim)
{
if (getrlimit(limit, rlim))
fprintf(stderr, "Failed in getrlimit\n");
printf("%15s=%2d: cur=%20lu, max=%20lu\n", limit_string,
limit, rlim->rlim_cur, rlim->rlim_max);
}
void print_limits(void)
{
struct rlimit rlim;
do_limit(RLIMIT_CPU, "RLIMIT_CPU", &rlim);
do_limit(RLIMIT_FSIZE, "RLMIT_FSIZE", &rlim);
do_limit(RLIMIT_DATA, "RLMIT_DATA", &rlim);
do_limit(RLIMIT_STACK, "RLIMIT_STACK", &rlim);
do_limit(RLIMIT_CORE, "RLIMIT_CORE", &rlim);
do_limit(RLIMIT_RSS, "RLIMIT_RSS", &rlim);
do_limit(RLIMIT_NPROC, "RLIMIT_NPROC", &rlim);
do_limit(RLIMIT_NOFILE, "RLIMIT_NOFILE", &rlim);
do_limit(RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK", &rlim);
do_limit(RLIMIT_AS, "RLIMIT_AS", &rlim);
do_limit(RLIMIT_LOCKS, "RLIMIT_LOCKS", &rlim);
}
void print_rusage(int who)
{
struct rusage usage;
if (getrusage(who, &usage))
DEATH("getrusage failed");
if (who == RUSAGE_SELF)
printf("For RUSAGE_SELF\n");
if (who == RUSAGE_CHILDREN)
printf("\nFor RUSAGE_CHILDREN\n");
printf
("ru_utime.tv_sec, ru_utime.tv_usec = %4d %4d (user time used)\n",
(int)usage.ru_utime.tv_sec, (int)usage.ru_utime.tv_usec);
printf
("ru_stime.tv_sec, ru_stime.tv_usec = %4d %4d (system time used)\n",
(int)usage.ru_stime.tv_sec, (int)usage.ru_stime.tv_usec);
printf("ru_maxrss = %4ld (max resident set size)\n", usage.ru_maxrss);
printf("ru_ixrss = %4ld (integral shared memory size)\n",
usage.ru_ixrss);
printf("ru_idrss = %4ld (integral unshared data size)\n",
usage.ru_idrss);
printf("ru_isrss = %4ld (integral unshared stack size)\n",
usage.ru_isrss);
printf("ru_minflt = %4ld (page reclaims)\n", usage.ru_minflt);
printf("ru_majflt = %4ld (page faults)\n", usage.ru_majflt);
printf("ru_nswap = %4ld (swaps)\n", usage.ru_nswap);
printf("ru_inblock = %4ld (block input operations)\n",
usage.ru_inblock);
printf("ru_oublock = %4ld (block output operations)\n",
usage.ru_oublock);
printf("ru_msgsnd = %4ld (messages sent)\n", usage.ru_msgsnd);
printf("ru_msgrcv = %4ld (messages received)\n", usage.ru_msgrcv);
printf("ru_nsignals= %4ld (signals received)\n", usage.ru_nsignals);
printf("ru_nvcsw= %4ld (voluntary context switches)\n",
usage.ru_nvcsw);
printf("ru_nivcsw= %4ld (involuntary context switches)\n",
usage.ru_nivcsw);
}
int main(int argc, char *argv[])
{
struct rlimit rlim;
pid_t pid = 0;
int status = 0, nchildren = 3, i;
/* Print out all limits */
printf("Printing out all limits for pid=%d:\n", getpid());
print_limits();
/* change and printout the limit for core file size */
printf("\nBefore Modification, this is RLIMIT_CORE:\n");
do_limit(RLIMIT_CORE, "RLIMIT_CORE", &rlim);
rlim.rlim_cur = 8 * 1024 * 1024;
printf("I forked off a child with pid = %d\n", (int)pid);
setrlimit(RLIMIT_CORE, &rlim);
printf("\nAfter Modification, this is RLIMIT_CORE:\n");
do_limit(RLIMIT_CORE, "RLIMIT_CORE", &rlim);
/* fork off the nchildren */
fflush(stdout);
for (i = 0; i < nchildren; i++) {
pid = fork();
if (pid < 0)
DEATH("Failed in fork");
if (pid == 0) { /* any child */
printf("\nIn child pid= %d this is RLIMIT_CORE:\n",
(int)getpid());
do_limit(RLIMIT_CORE, "RLIMIT_CORE", &rlim);
fflush(stdout);
sleep(3);
exit(EXIT_SUCCESS);
}
}
while (pid > 0) { /* parent */
pid = wait(&status);
printf("Parent got return on pid=%d\n", (int)pid);
}
printf(" **************************************************** \n");
print_rusage(RUSAGE_SELF);
print_rusage(RUSAGE_CHILDREN);
exit(EXIT_SUCCESS);
}
测试
gcc resource_limit.c -o resource_limit
./resource_limit
Printing out all limits for pid=6743:
RLIMIT_CPU= 0: cur=18446744073709551615, max=18446744073709551615
RLMIT_FSIZE= 1: cur=18446744073709551615, max=18446744073709551615
RLMIT_DATA= 2: cur=18446744073709551615, max=18446744073709551615
RLIMIT_STACK= 3: cur= 8388608, max=18446744073709551615
RLIMIT_CORE= 4: cur=18446744073709551615, max=18446744073709551615
RLIMIT_RSS= 5: cur=18446744073709551615, max=18446744073709551615
RLIMIT_NPROC= 6: cur= 15502, max= 15502
RLIMIT_NOFILE= 7: cur= 1024, max= 524288
RLIMIT_MEMLOCK= 8: cur= 8388608, max= 8388608
RLIMIT_AS= 9: cur=18446744073709551615, max=18446744073709551615
RLIMIT_LOCKS=10: cur=18446744073709551615, max=18446744073709551615
Before Modification, this is RLIMIT_CORE:
RLIMIT_CORE= 4: cur=18446744073709551615, max=18446744073709551615
I forked off a child with pid = 0
After Modification, this is RLIMIT_CORE:
RLIMIT_CORE= 4: cur= 8388608, max=18446744073709551615
In child pid= 6744 this is RLIMIT_CORE:
RLIMIT_CORE= 4: cur= 8388608, max=18446744073709551615
In child pid= 6745 this is RLIMIT_CORE:
RLIMIT_CORE= 4: cur= 8388608, max=18446744073709551615
In child pid= 6746 this is RLIMIT_CORE:
RLIMIT_CORE= 4: cur= 8388608, max=18446744073709551615
Parent got return on pid=6744
Parent got return on pid=6745
Parent got return on pid=6746
Parent got return on pid=-1
****************************************************
For RUSAGE_SELF
ru_utime.tv_sec, ru_utime.tv_usec = 0 0 (user time used)
ru_stime.tv_sec, ru_stime.tv_usec = 0 906 (system time used)
ru_maxrss = 15016 (max resident set size)
ru_ixrss = 0 (integral shared memory size)
ru_idrss = 0 (integral unshared data size)
ru_isrss = 0 (integral unshared stack size)
ru_minflt = 107 (page reclaims)
ru_majflt = 0 (page faults)
ru_nswap = 0 (swaps)
ru_inblock = 0 (block input operations)
ru_oublock = 0 (block output operations)
ru_msgsnd = 0 (messages sent)
ru_msgrcv = 0 (messages received)
ru_nsignals= 0 (signals received)
ru_nvcsw= 1 (voluntary context switches)
ru_nivcsw= 0 (involuntary context switches)
For RUSAGE_CHILDREN
ru_utime.tv_sec, ru_utime.tv_usec = 0 0 (user time used)
ru_stime.tv_sec, ru_stime.tv_usec = 0 617 (system time used)
ru_maxrss = 1204 (max resident set size)
ru_ixrss = 0 (integral shared memory size)
ru_idrss = 0 (integral unshared data size)
ru_isrss = 0 (integral unshared stack size)
ru_minflt = 105 (page reclaims)
ru_majflt = 0 (page faults)
ru_nswap = 0 (swaps)
ru_inblock = 0 (block input operations)
ru_oublock = 0 (block output operations)
ru_msgsnd = 0 (messages sent)
ru_msgrcv = 0 (messages received)
ru_nsignals= 0 (signals received)
ru_nvcsw= 6 (voluntary context switches)
ru_nivcsw= 6 (involuntary context switches)
设置优先级
编写一个用户进程,使用setpriority()来修改进程的优先级,然后使用getpriority()函数验证
代码
process_priority.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
int main(int argc, char *argv[])
{
pid_t mypid;
int old_prio, new_prio, i, rc;
if (argc > 1) {
mypid = atoi(argv[1]);
} else {
mypid = getpid();
}
printf("\nExamining priorities forPID = %d \n", mypid);
printf("%10s%10s%10s\n", "Previous", "Requested", "Assigned");
for (i = -20; i < 20; i += 2) {
old_prio = getpriority(PRIO_PROCESS, (int)mypid);
rc = setpriority(PRIO_PROCESS, (int)mypid, i);
if (rc)
fprintf(stderr, "setpriority() failed ");
/* must clear errno before call to getpriority
because -1 is a valid return value */
errno = 0;
new_prio = getpriority(PRIO_PROCESS, (int)mypid);
printf("%10d%10d%10d\n", old_prio, i, new_prio);
}
exit(EXIT_SUCCESS);
}
测试
sudo ./process_priority
Examining priorities forPID = 7212
Previous Requested Assigned
0 -20 -20
-20 -18 -18
-18 -16 -16
-16 -14 -14
-14 -12 -12
-12 -10 -10
-10 -8 -8
-8 -6 -6
-6 -4 -4
-4 -2 -2
-2 0 0
0 2 2
2 4 4
4 6 6
6 8 8
8 10 10
10 12 12
12 14 14
14 16 16
16 18 18
per-cpu变量
创建一个per-cpu变量,并且初始化该per-cpu变量,修改per-cpu变量的值,然后输出这些值
per-cpu变量是Linux内核中同步机制的一种。当系统中所有的CPU都访问共享的一个变量v时,CPU0修改了变量v的值时,CPU1也在同时修改变量v的值,那么就会导致变量v值不正确。一个可行的办法就是CPU0访问变量v时使用原子加锁指令,CPU1访问变量v时只能等待了,可是这会有两个比较明显的缺点。
- 原子操作是比较耗时的。
- 现代处理器中,每个CPU都有L1缓存,那么多CPU同时访问同一个变量时会导致缓存一致性问题。当某个CPU对共享数据变量v修改后,其他CPU上对应的缓存行需要做无效操作,这对性能是有所损耗的。
per-cpu 变量为了解决上述问题出现一种有趣的特性,它为系统中每个处理器都分配该变量的副本。这样在多处理器系统中,当处理器只能访问属于它自己的那个变量副本,不需要考虑与其他处理器的竞争问题,还能充分利用处理器本地的硬件缓存来提升性能。
代码
percpu.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/percpu.h>
#include <linux/cpumask.h>
// 指定license版本
MODULE_LICENSE("GPL");
// 作者信息
MODULE_AUTHOR("Marvin");
// 模块描述
MODULE_DESCRIPTION("process percpu demo");
// 提供别名
MODULE_ALIAS("processpercpu");
static DEFINE_PER_CPU(long, cpuvar) = 10;
static long __percpu *cpualloc;
static int __init my_init(void)
{
int cpu;
pr_info("module loaded at 0x%p\n", my_init);
/* modify the cpuvar value */
for_each_possible_cpu(cpu){
per_cpu(cpuvar, cpu) = 15;
pr_info("init: cpuvar on cpu%d = %ld\n",
cpu, get_cpu_var(cpuvar));
put_cpu_var(cpuvar);
}
__this_cpu_write(cpuvar, 20);
/* alloc a percpu value */
cpualloc = alloc_percpu(long);
/* set all cpu for this value */
for_each_possible_cpu(cpu){
*per_cpu_ptr(cpualloc, cpu) = 100;
pr_info("init: cpu:%d cpualloc = %ld\n",
cpu, *per_cpu_ptr(cpualloc, cpu));
}
return 0;
}
static void __exit my_exit(void)
{
int cpu;
pr_info("exit module...\n");
for_each_possible_cpu(cpu) {
pr_info("cpuvar cpu%d = %ld\n", cpu, per_cpu(cpuvar, cpu));
pr_info("exit: cpualloc%d = %ld\n", cpu, *per_cpu_ptr(cpualloc, cpu));
}
free_percpu(cpualloc);
pr_info("Bye: module unloaded from 0x%p\n", my_exit);
}
module_init(my_init);
module_exit(my_exit);
Makefile
ifneq ($(KERNELRELEASE),)
MODULE_NAME = processpercpu
$(MODULE_NAME)-objs := percpu.o
obj-m := $(MODULE_NAME).o
else
KERNEL_DIR = /lib/modules/`uname -r`/build
MODULEDIR := $(shell pwd)
.PHONY: modules
default: modules
modules:
make -C $(KERNEL_DIR) M=$(MODULEDIR) modules
clean distclean:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
rm -f *.o *.mod.c .*.*.cmd *.ko
rm -rf .tmp_versions
endif
测试
sudo insmod processpercpu.ko
sudo rmmod processpercpu.ko
内核日志
[ 5120.592012] module loaded at 0x00000000e4845e2e
[ 5120.592017] init: cpuvar on cpu0 = 15
[ 5120.592018] init: cpuvar on cpu1 = 15
[ 5120.592019] init: cpuvar on cpu2 = 15
[ 5120.592020] init: cpuvar on cpu3 = 15
[ 5120.592023] init: cpu:0 cpualloc = 100
[ 5120.592024] init: cpu:1 cpualloc = 100
[ 5120.592025] init: cpu:2 cpualloc = 100
[ 5120.592026] init: cpu:3 cpualloc = 100
[ 5129.730217] exit module...
[ 5129.730219] cpuvar cpu0 = 20
[ 5129.730220] exit: cpualloc0 = 100
[ 5129.730221] cpuvar cpu1 = 15
[ 5129.730221] exit: cpualloc1 = 100
[ 5129.730222] cpuvar cpu2 = 15
[ 5129.730223] exit: cpualloc2 = 100
[ 5129.730223] cpuvar cpu3 = 15
[ 5129.730224] exit: cpualloc3 = 100
[ 5129.730225] Bye: module unloaded from 0x00000000cb3a0059

浙公网安备 33010602011771号