我们被要求创建五个内核线程,它们将全局计数器一一递增。我是内核空间编程的新手,所以我很难做到这一点-特别是处理内核线程和使用自旋锁。
这是我的代码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
static spinlock_t my_lock = __SPIN_LOCK_UNLOCKED();
static struct task_struct *t1;
static struct task_struct *t2;
static struct task_struct *t3;
static struct task_struct *t4;
static struct task_struct *t5;
static int o;
typedef struct __counter_t {
int value;
} counter_t;
void init (counter_t *c) {
c->value = 0;
}
void increment (counter_t *c) {
spin_trylock(&my_lock);
c->value++;
spin_unlock(&my_lock);
}
int get(counter_t *c) {
int rc;
spin_trylock(&my_lock);
rc = c->value;
spin_unlock(&my_lock);
return rc;
}
static int t1_f(void *unused)
{
int i=0;
struct __counter_t *ctr1=kmalloc(sizeof(struct __counter_t), GFP_KERNEL);
init(ctr1);
for(i=0; i<5000; i++)
{
increment(ctr1);
}
o = get(ctr1);
printk(KERN_INFO "Counter: %d\n",o);
kfree(ctr1);
msleep(1000);
return 0;
}
static int t2_f(void *unused)
{
int j=0;
struct __counter_t *ctr2=kmalloc(sizeof(struct __counter_t), GFP_KERNEL);
init(ctr2);
for(j=0; j<5000; j++)
{
increment(ctr2);
}
o = o + get(ctr2);
printk(KERN_INFO "Counter: %d\n",o);
kfree(ctr2);
msleep(1000);
return 0;
}
static int t3_f(void *unused)
{
int k=0;
struct __counter_t *ctr3=kmalloc(sizeof(struct __counter_t), GFP_KERNEL);
init(ctr3);
for(k=0; k<5000; k++)
{
increment(ctr3);
}
o = o + get(ctr3);
printk(KERN_INFO "Counter: %d\n",o);
kfree(ctr3);
msleep(1000);
return 0;
}
static int t4_f(void *unused)
{
int l=0;
struct __counter_t *ctr4=kmalloc(sizeof(struct __counter_t), GFP_KERNEL);
init(ctr4);
for(l=0; l<5000; l++)
{
increment(ctr4);
}
o = o + get(ctr4);
printk(KERN_INFO "Counter: %d\n",o);
kfree(ctr4);
msleep(1000);
return 0;
}
static int t5_f(void *unused)
{
int m=0;
struct __counter_t *ctr5=kmalloc(sizeof(struct __counter_t), GFP_KERNEL);
init(ctr5);
for(m=0; m<5000; m++)
{
increment(ctr5);
}
o = o + get(ctr5);
printk(KERN_INFO "Counter: %d\n",o);
kfree(ctr5);
msleep(1000);
return 0;
}
static int __init init_thread(void)
{
int f=0;
int h=0;
printk(KERN_INFO "Thread Creating....\n");
t1 = kthread_create(t1_f, NULL, "mythread1");
t2 = kthread_create(t2_f, NULL, "mythread2");
t3 = kthread_create(t3_f, NULL, "mythread3");
t4 = kthread_create(t4_f, NULL, "mythread4");
t5 = kthread_create(t5_f, NULL, "mythread5");
if((((t1 && t2) && t3)&& t4)&&t5)
{
printk(KERN_INFO "Thread Created Successfully\n");
while(!h) {
if(f==0)
{
spin_trylock(&my_lock);
wake_up_process(t1);
spin_unlock(&my_lock);
f=1;
}
else if(f==1)
{
spin_trylock(&my_lock);
wake_up_process(t2);
spin_unlock(&my_lock);
f=2;
}
else if(f==2)
{
spin_trylock(&my_lock);
wake_up_process(t3);
spin_unlock(&my_lock);
f=3;
}
else if(f==3)
{
spin_trylock(&my_lock);
wake_up_process(t4);
spin_unlock(&my_lock);
f=4;
}
else if(f==4)
{
spin_trylock(&my_lock);
wake_up_process(t5);
spin_unlock(&my_lock);
h=1;
}
}
}
else
{
printk(KERN_ALERT "Thread Creation Failed\n");
}
return 0;
}
static void __exit cleanup_thread(void)
{
printk(KERN_INFO "Cleaning up.....\n");
}
module_init(init_thread);
module_exit(cleanup_thread);
结果应为:
counter: 5000
counter: 10000
counter: 15000
counter: 20000
counter: 25000
但是相反,我得到的是(错误)结果的变化,例如:
counter: 5000
counter: 10000
counter: 5000
counter: 10000
counter: 15000
是否有正确的方法(特别是使用自旋锁,因为我觉得那是我犯错的地方)?任何帮助将不胜感激。谢谢!
答案 0 :(得分:0)
什么保护变量o;如o = o + get(ctr {0..n})?查看您的代码,对于某些计数器(例如ctr2),您可以使用自旋锁保护其更新,但是其他线程是否真的有可能访问该计数器?似乎它是线程本地的,因此并不需要保护;而所有线程共享的“ o”确实需要保护。
作为一般说明,当您发现自己剪切+粘贴相同的函数时,仅通过几个变量将它们区分开,很可能您已经找到了单个更通用函数的参数的理想候选者。这不仅在眼睛上更容易(不易阅读和验证),而且更易于进行实验。将手动编辑应用于十几个位置会很快变旧...