设为首页 加入收藏

TOP

Linux下产生死锁问题分析(一)
2014-11-24 01:04:16 来源: 作者: 【 】 浏览:6
Tags:Linux 生死 问题 分析

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。死锁要产生必须具备四个必要条件:1. 互斥条件 2. 请求和保持条件 3.不可剥夺条件 4. 环路等待条件。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。

下面举一个Linux环境下产生死锁的程序(首先是驱动部分):



#include
#include
#include
#include
#include
#include
#include
#include
#include

MODULE_LICENSE("GPL");


#define init_MUTEX(LOCKNAME) sema_init(LOCKNAME,1)



#define DEVICE_NAME "CDEV_ZHU"
static struct class *cdev_class;


struct cdev dev_c;
dev_t dev;

static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);
static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);

struct file_operations globalvar_fops =
{
read: globalvar_read, write: globalvar_write,
};

static int global_var = 0;
static struct semaphore sem;
static wait_queue_head_t outq;
static int flag = 0;

static int __init globalvar_init(void)
{
int ret,err;
ret = alloc_chrdev_region(&dev,0,1,DEVICE_NAME) ;
if (ret)
{
printk("globalvar register failure");
}
else
{

cdev_init(&dev_c,&globalvar_fops);

err = cdev_add(&dev_c,dev,1);

if(err)
{
printk(KERN_NOTICE "error %d adding FC_dev\n",err);
unregister_chrdev_region(dev, 1);
return err;
}
else
{
printk("device register success! \n");
}

cdev_class = class_create(THIS_MODULE,DEVICE_NAME);
if(IS_ERR(cdev_class))
{
printk("ERR:cannot create a cdev_class\n");
unregister_chrdev_region(dev, 1);
return -1;
}
device_create(cdev_class, NULL, dev, 0, DEVICE_NAME);

init_MUTEX(&sem);
init_waitqueue_head(&outq);
}
return ret;
}



static void __exit globalvar_exit(void)
{
device_destroy(cdev_class,dev);
class_destroy(cdev_class);
unregister_chrdev_region(dev,1);
printk("globalvar exit \n");
}


static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
{

/*
//正常情况下这里不应该注释,顺序应该是先wait_event_interruptible,再down_interruptible才不会导致死锁
if (wait_event_interruptible(outq, flag != 0))
{
return - ERESTARTSYS;
}
*/
if (down_interruptible(&sem))
{
return - ERESTARTSYS;
}


/*
交换了 down_interruptible 和 wait_event_interruptible 会造成死锁通过添加打印语句,可以发现会打印 “size semaphore”其它的像“wake up”,
global_write()函数中的”write_down”和”waking up” 都不会打印,说明在up(&sem)之后 global_read()会立刻获取该信号量,然后进入睡眠。
*/
printk(“size semaphore \n”);


if (wait_event_interruptible(outq, flag != 0))
{
return - ERESTARTSYS;
}


printk("wake up !\n");

flag = 0;
if (copy_to_user(buf, &global_var, sizeof(int)))
{
up(&sem);
return - EFAULT;
}

up(&sem);

return sizeof(int);
}

static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
if (down_interruptible(&sem))
{
return - ERESTARTSYS;
}
if (copy_from_user(&global_var, buf, sizeof(int)))
{
up(&sem);
return - EFAULT;
}
up(&sem);
flag = 1;
printk("write done!\n");
wake_up_interruptible(&outq);
printk("waking up \n");
return sizeof(int);
}

module_init(globalvar_init);
module_exit(globalvar_exit);


/* /kernel/semaphore.c */
void up(struct semaphore *sem)
{
unsigned long flags;


spin_lock_irqsave(&sem->lock, flags);
if (likely(list_empty(&sem->wait_list)))
sem->count++;
else
__up(sem);
spin_unlock_irqrestore(&sem-

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇驱动支持select函数 下一篇Linux字符驱动中动态分配设备号与..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: