死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。死锁要产生必须具备四个必要条件:1. 互斥条件 2. 请求和保持条件 3.不可剥夺条件  4. 环路等待条件。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。
 
下面举一个Linux环境下产生死锁的程序(首先是驱动部分):
#include <linux/module.h> 
#include <linux/init.h> 
#include <linux/fs.h> 
#include <asm/uaccess.h> 
#include <linux/wait.h> 
#include <linux/semaphore.h> 
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/sched.h>
 
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);
