Linux OS内核 作业二:多线程访问

实验题目:

http://gauss.ececs.uc.edu/Courses/c4029/labs/lab3.html

大致内容就是多个线程访问同一个变量,变量累加。然后记录变量在累加的过程中被访问的次数。(不知道有没有说清楚,方正是挺拗口的)。

未同步时的情况

#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内核 作业三:设备驱动与读写信号量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值