Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1638657
  • 博文数量: 197
  • 博客积分: 10046
  • 博客等级: 上将
  • 技术积分: 1983
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-07 12:36
个人简介

在外企做服务器开发, 目前是项目经理, 管理两个server开发的项目。不做嵌入式好久了。

文章分类
文章存档

2011年(2)

2010年(6)

2009年(18)

2008年(30)

2007年(100)

2006年(41)

分类: LINUX

2007-09-28 12:50:34

【kernel编程进阶练习3】归纳总结互斥的用法

总结一下, 我们写module的时候, 常用的简单的互斥的例子:

注意 ,我这三个例子, 都是在2.4.24 kernel下测试的, 如果要用在2.6上,可能需要做相应的更改和调整, 自己改好以后, 贴上来!

以下是个一个例子, 只有一个进程才能打开open() , 其他的进程不可以,直接返回。大家可以比较一下优劣。

用信号量:

CODE:
static DECLARE_MUTEX(char_sem);//2.6 kernel: static DEFINE_MUTEX(rtc_mutex);
static unsigned long char_inuse;
static int device_open(struct inode *inode, struct file *file)
{
        static int counter = 0;
        down_interruptible(&char_sem);//2.6 kernel: mutex_lock(&char_mutex);
        if(char_inuse == 1) {
                up(&char_sem);
                return -EBUSY;
        }
        char_inuse = 1;
        up(&char_sem);//2.6 kernel: mutex_unlock(&char_sem);

        try_module_get(THIS_MODULE);
        ...........
}
static int device_release(struct inode *inode, struct file *file)
{
        char_inuse = 0;
        module_put(THIS_MODULE);

        return 0;
}

用原子变量:

CODE:
static atomic_t inuse_atomic = ATOMIC_INIT(-1);

/* 这个动作有可能并发,这里我又改成原子变量了
*/
static int device_open(struct inode *inode, struct file *file)
{

        if(  ! atomic_inc_and_test(&inuse_atomic)) //原子加1 , 并判断是否==0  , -1 , 表示无人使用此设备
        {
                dbg("%d process is opening this device \n",inuse_atomic);//如果值是1 , 说明刚好有一个进程在访问该设备
                dbg("open device failure \n");
                return -EBUSY;
        }
        //try_module_get(THIS_MODULE);//2.6 kernel
        try_module_get(THIS_MODULE);
        return SUCCESS;
}
static int device_release(struct inode *inode, struct file *file)
{
        atomic_set(&inuse_atomic,-1);//重新再把它置成-1
        module_put(THIS_MODULE);

        return 0;
}

用原子的bit操作

CODE:
static int chardev_users = 0;  //防止互斥, 这里用更严格的test_and_set_bit() 函数
static int device_open(struct inode *inode, struct file *file)
{
        static int counter = 0;
        // if (Device_Open)
        //  return -EBUSY;
        // Device_Open++;
        // 上面的办法太不可靠了。用原子操作或者bit操作才是最可靠的。
        if(test_and_set_bit(0,&chardev_users))
        return -EBUSY;
        //sprintf(msg, "I already told you %d times Hello world!\n", counter++);
        //memset(msg,'\0',sizeof(msg));
        msg_Ptr = msg;
        //try_module_get(THIS_MODULE);
        try_module_get(THIS_MODULE);  //increase the flag to present the module is used
        /* strategy :
        * you should here allocate resources , not in init_module() ,if(refer == 0)
        */
        return SUCCESS;
}
static int device_release(struct inode *inode, struct file *file)
{
        // Device_Open--;  /* We're now ready for our next caller */
        //chardev_users =0; //直到现在才可以被别人open()
        //set_bit() is better by me
        if( !test_and_clear_bit(0,&chardev_users))  //bit0 should be 1
        dbg("It looks wrong ,lock may bad \n");
        module_put(THIS_MODULE);
阅读(2561) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~