linux驱动自旋锁问题

  我是一个linux驱动新手,今天在学习关于驱动的自旋锁spinlock时遇到了一个问题:在加载好我所编译的驱动后,运行读写测试程序,该程序只能运行一次,第二次运行时电脑死机(虚拟机死机)。

     我的驱动程序的思路是,创建了一个可读写的字符设备,并使file_operations中的open和release的指向函数的指针分别指向了一个函数。

初始化spinlock是在全局变量时:如:

static spinlock_t my_lock=SPIN_LOCK_UNLOCKED;   /*定义自旋锁,并初始化自旋锁*/

    并在指向open的函数中放了一条:spin_lock(&my_lock);

     在指向release函数中放置一条:spin_unlock(&my_lock);

     其余read和write函数正常;

下面即是我编写的程序:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/semaphore.h>
#include <linux/sched.h>  /*copy_to_user() copy_from_user*/
#include <linux/spinlock.h>

MODULE_LICENSE("GPL");
static dev_t my_num;
static struct cdev *my_cdev1;
static int globver=1;
//static int globavar_count=0;    
static struct semaphore sem;      /*定义信号量*/
static spinlock_t my_lock=SPIN_LOCK_UNLOCKED;   /*定义自旋锁,并初始化自旋锁*/
//static struct inode *inode1;
//static struct file *file1;
static int r=0,w=0;


static ssize_t cdev_read(struct file *,char __user *,size_t,loff_t *);
static ssize_t cdev_write(struct file *,const char *,size_t,loff_t *);
static int cdev_open(struct inode *,struct file *);
static int cdev_release(struct inode *,struct file *);

static struct file_operations f_op={
.owner=THIS_MODULE,
.read=cdev_read,
.write=cdev_write,
.open=cdev_open,
.release=cdev_release,
};


/*read*/
static ssize_t cdev_read(struct file *flip,char *buf,size_t count,loff_t *f_pos)
{
if(down_interruptible(&sem))   /*获取信号量以中断的方式*/
{
return -ERESTARTSYS;
}

if(copy_to_user(buf,&globver,sizeof(int)))
{
up(&sem);/*释放信号量*/
return -EFAULT;
}
printk("enter read2 in process %d/tin %d\n",current->pid,r++);
up(&sem);
return sizeof(int);
}

/*write*/
static ssize_t cdev_write(struct file *filp,const char *buf,size_t len,loff_t *off)
{
if(down_interruptible(&sem)) //获取信号量,以可中断的方式
return -ERESTARTSYS;

if(copy_from_user(&globver,buf,sizeof(int)))
{
up(&sem);    /*释放信号量*/
return -EFAULT;
}
printk(KERN_ALERT"enter write2 in process %d/tin %d\n",current->pid,w++);
up(&sem);   /*释放信号量*/
return sizeof(int);
}


/*open*/
int cdev_open(struct inode *Inode,struct file *FIle)
{
//获得自旋锁
printk(KERN_ALERT"now I get the spinlock good luck!\n");
spin_lock(&my_lock);  
printk(KERN_ALERT"file open successful\n");
printk("the process \"%s\"(pid) is %d\n",current->comm,current->pid);
return 0;
}

/*release*/
int cdev_release(struct inode *Inode,struct file *fIle)
{
//释放信号量
up(&sem);
//释放自旋锁
printk(KERN_ALERT"NOW THE LOCK IS FREE GOOD LUCK TOO.\n");
spin_unlock(&my_lock);
printk("release is doing\n");
return 0;
}


/*初始化*/
static int  cdev_init1(void)
{
int cdev_major,cdev_minor;

int result,result2;
printk(KERN_ALERT"********************************************\n");
printk(KERN_NOTICE"welcome to my software about lk_spin_sema1\n");
printk(KERN_WARNING"*******************************************\n");


/*   获取主设备号        */
result=alloc_chrdev_region(&my_num,0,1,"spinlock_sema");
if(result==0)
{
printk(KERN_ALERT"register number succussful\n");
cdev_major=MAJOR(my_num);
printk("cdev MAJOR is %d\n",cdev_major);
cdev_minor=MINOR(my_num);
printk("cdev MINOR is %d\n",cdev_minor);
}
else
{
printk(KERN_ALERT"can't register number succussful\n");
return 0;
}

/*设备注册*/
my_cdev1=cdev_alloc();
my_cdev1->ops=&f_op;
result2=cdev_add(my_cdev1,my_num,1);
if(result2<0)
{printk(KERN_WARNING"mycdv:can't register\n");
unregister_chrdev_region(my_num,1);
return 0;
}
else {
printk("cdev register successful\n");
init_MUTEX(&sem);    //初始化信号量
}
}

 

/* 退出*/
static void  cdev_exit(void)
{
printk(KERN_ALERT"GoodBye my frends\n");
unregister_chrdev_region(my_num,1);
cdev_del(my_cdev1);

}


module_init(cdev_init1);
module_exit(cdev_exit);
MODULE_AUTHOR("YUZHIHUA");
MODULE_VERSION("V1.1");
MODULE_DESCRIPTION("register to cdev to use");

 

 


 

 

你可能感兴趣的:(linux,linux驱动)