实验题目:
大致内容就是多个线程访问同一个变量,变量累加。然后记录变量在累加的过程中被访问的次数。(不知道有没有说清楚,方正是挺拗口的)。
未同步时的情况
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/sched.h> //wake_up_process()
#include <linux/kthread.h> //kthread_create()、kthread_run()
#include <linux/time.h>
MODULE_LICENSE("GPL");
static int NUM = 1000000;
int arr[1000000] = {0};
int stat[1000000] = {0};
struct task_struct *t1;
struct task_struct *t2;
struct timeval start;
struct timeval end;
int idx = 0;
int cs1 = 0 , cs2 = 0;
//用来显示运行时间
void show_runningtime(void)
{
unsigned long diff;
diff = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec;
printk(KERN_INFO "thedifference is %ld\n",diff);
return 0;
}
//累加,并记录
int incrementer(void *ptr) {
printk(KERN_INFO "Consumer TID %d\n", (int)ptr);
while (idx < 1000000) {
arr[idx++] += 1;
if ((int)ptr == 1)
{
cs1++;
}else if ((int)ptr == 2)
{
cs2++;
}
schedule();
}
return 0;
}
//加载内核模块时
int init_module( void ) {
do_gettimeofday(&start);
int id1 = 1, id2 = 2;
t1 = kthread_create(incrementer, (void*)id1, "inc1");
t2 = kthread_create(incrementer, (void*)id2, "inc2");
if (t1 && t2) {
printk(KERN_INFO "Starting..\n");
wake_up_process(t1);
wake_up_process(t2);
} else {
printk(KERN_EMERG "Error\n");
}
return 0;
}
//卸载内核模块时,对统计的信息进行显示
void cleanup_module( void ) {
int tmp;
int i;
for (i = 0; i < NUM; i++)
{
tmp = arr[i];
stat[tmp]++;
}
int j;
for (j = 0; j < NUM; ++j)
{
if (stat[j] > 0)
{
printk(KERN_INFO "stat[%d]:%d \n",j,(stat[j]));
}
}
printk(KERN_INFO "cs1:%d\tcs2:%d\tcs1+cs2=%d\t",cs1,cs2,cs1+cs2);
do_gettimeofday(&end);
show_runningtime();
return;
}
注:
1. 关于显示运行时间的问题,可以参考我的另一篇博文:http://blog.csdn.net/u013806583/article/details/58127067
2. 关于如何编译、加载和卸载内核模块,可以参考《Linux OS内核 作业一》的方法:http://blog.csdn.net/u013806583/article/details/58604378
加锁同步后
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/sched.h> //wake_up_process()
#include <linux/kthread.h> //kthread_create()、kthread_run()
#include <linux/semaphore.h> //信号量
#include <linux/time.h> //计算运行时间
MODULE_LICENSE("GPL");
static int NUM = 1000000;
int arr[1000000] = {0};
int stat[1000000] = {0};
struct task_struct *t1;
struct task_struct *t2;
//信号量,用于同步
struct semaphore lock;
struct timeval start;
struct timeval end;
int idx = 0;
int cs1 = 0 , cs2 = 0;
int incrementer(void *ptr) {
printk(KERN_INFO "Consumer TID %d\n", (int)ptr);
while (idx < 1000000) {
//加锁
if(!down_interruptible(&lock))
{
arr[idx++] += 1;
}
if ((int)ptr == 1)
{
cs1++;
}else if ((int)ptr == 2)
{
cs2++;
}
//释放锁
up(&lock);
schedule();
}
return 0;
}
void show_runningtime(void)
{
unsigned long diff;
diff = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec;
printk(KERN_INFO "thedifference is %ld\n",diff);
return 0;
}
int init_module( void ) {
// start timing
do_gettimeofday(&start);
int id1 = 1, id2 = 2;
t1 = kthread_create(incrementer, (void*)id1, "inc1");
t2 = kthread_create(incrementer, (void*)id2, "inc2");
//初始化索
sema_init(&lock, 1);
if (t1 && t2) {
printk(KERN_INFO "Starting..\n");
wake_up_process(t1);
wake_up_process(t2);
} else {
printk(KERN_EMERG "Error\n");
}
return 0;
}
void cleanup_module( void ) {
int tmp;
int i;
for (i = 0; i < NUM; i++)
{
tmp = arr[i];
stat[tmp]++;
}
int j;
for (j = 0; j < NUM; ++j)
{
if (stat[j] > 0)
{
printk(KERN_INFO "stat[%d]:%d \n",j,(stat[j]));
}
}
printk(KERN_INFO "cs1:%d\tcs2:%d\tcs1+cs2=%d\t",cs1,cs2,cs1+cs2);
do_gettimeofday(&end);
show_runningtime();
return;
}
观察运行结果:
未加锁同步:
加锁同步:
系列博客:
相信当你需要其中一个的时候,也一定需要剩下的两个
Linux OS内核 作业一:kthread和workqueue
Linux OS内核 作业二:多线程访问
Linux OS内核 作业三:设备驱动与读写信号量