Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1315466
  • 博文数量: 213
  • 博客积分: 7590
  • 博客等级: 少将
  • 技术积分: 2185
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-31 17:31
个人简介

热爱开源,热爱linux

文章分类

全部博文(213)

文章存档

2018年(4)

2017年(1)

2015年(1)

2014年(5)

2013年(2)

2012年(2)

2011年(21)

2010年(82)

2009年(72)

2008年(23)

分类: LINUX

2010-07-26 20:46:58

 继一个简单的字符驱动程序<2>(实现并发控制)  用互斥锁访问字符设备后,使用自旋锁保护访问资源.自旋锁互斥锁是相似的,不同的是,进程在无法得到自旋锁保护的资源后,不会进入等待状态,而是反复检查自旋锁是否已经释放。
下面是对一个简单的字符驱动程序<2>(实现并发控制)  中的cjf_chdev.c进行修改后的程序,用来实现自旋锁的机制.

/***********************************************************************
 *文件名称:cjf_chdev.c
 *简要描述:本程序使用自旋锁对设备反问进行限制
 *当前版本:3.0
 *作者:Ceagle
 *修改版本:1.0
 ***********************************************************************/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <asm/uaccess.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ceagle");

#define MAJOR_NUM 250 //定义主设备号为250,如果为0,表示内核动态分配设备号

#define DEVICE_NAME "cjf_chdev" //定义设备号的名称

#define DATA_NUM 20 //写入设备的字符串的最大长度


//声明打开设备函数

static int cjf_chdev_open(struct inode *inode,struct file *filp);
//声明释放设备函数

static int cjf_chdev_release(struct inode *inode,struct file *filp);
//声明读数据函数

static ssize_t cjf_chdev_read(struct file *filp,char *,size_t,loff_t *);
//声明写数据函数

static ssize_t cjf_chdev_write(struct file *filp,char *,size_t,loff_t *);

//定义写入设备的字符串数组

static char cjf_chdev_var[DATA_NUM] ;
static int cjf_chdev_count = 0;
static spinlock_t spin = SPIN_LOCK_UNLOCKED;

static const struct file_operations cjf_chdev_fops =
{
    .open = cjf_chdev_open,
    .release = cjf_chdev_release,
    .read = cjf_chdev_read,
    .write = cjf_chdev_write,
};

int cjf_chdev_open (struct inode *inode,struct file *filp)
{
    spin_lock(&spin);//用于获得自旋锁,如果获得自旋锁spin则返回,否则继续等待

    if (cjf_chdev_count) {
        spin_unlock(&spin);
        return -EBUSY;
    }
    cjf_chdev_count ++;
    spin_unlock(&spin);
    return 0;
}

int cjf_chdev_release(struct inode *inode,struct file *filp)
{
    cjf_chdev_count --;
    return 0;
}

static ssize_t cjf_chdev_read(struct file *filp,char *buf,size_tcount,loff_t *f_pos)
{    //从内核拷贝数据到用户空间

    if (copy_to_user(buf,&cjf_chdev_var,sizeof(cjf_chdev_var))) {
        return -EFAULT;
    }
    return sizeof(cjf_chdev_var);
}
static ssize_t cjf_chdev_write(struct file *filp,char *buf,size_tcount,loff_t *f_pos)
{
    //从用户空间拷贝数据到内核空间

    if (copy_from_user(&cjf_chdev_var,buf,sizeof(cjf_chdev_var))) {
        return -EFAULT;
    }
    return sizeof(cjf_chdev_var);
}

static int __init cjf_chdev_init(void)
{
    int reg;

    //使用函数register_chrdev将主设备号和设备名注册到内核中,

    //如果注册成功,返回0,否则返回负数;

    //如果成功注册动态分配的设备,则返回设备号

    reg = register_chrdev(MAJOR_NUM,DEVICE_NAME,&cjf_chdev_fops);
    if (reg) {
        printk("register fail!\n");
    } else {
        printk("register success!\n");
    }
    return reg;
}

static void __exit cjf_chdev_exit(void)
{
      //使用register_chrdev将设备号和设备名从内核卸载

    unregister_chrdev(MAJOR_NUM,DEVICE_NAME);
    printk("chardev has been unregistered!\n");
}

module_init(cjf_chdev_init);
module_exit(cjf_chdev_exit);


在用自旋锁后,当两个以上进程并发访问cjf_chdev设备时,在一个进程中打开cjf_chdev后,别的进程无法在访问cjf_chdev设备.
在一个终端运行test程序如下:
ceagle@ceagle-desktop:~/Code/Kernel/mychardev/mychdev3$ sudo ./test
open device cjf_chdev success!
write to cjf_chdev some data
而同时在另一个终端运行时则出现下列情况
ceagle@ceagle-desktop:~/Code/Kernel/mychardev/mychdev3$ sudo ./test
open device cjf_chdev faild!

如此可以理解自旋锁的一些机制了
更多阅读:
一个简单的字符驱动程序<1>
一个简单的字符驱动程序<2>(实现并发控制)
一个简单的字符驱动程序<4>(同步控制)

一个简单的字符驱动程序<5>(中断处理)



阅读(1308) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~