linux字符设备驱动-同步互斥阻塞笔记

本文介绍了Linux字符设备驱动中实现互斥和阻塞的方法,包括原子操作、信号量的使用,以及阻塞和非阻塞操作的实现。通过原子变量和信号量确保同一时间只有一个进程访问设备,同时讲解了根据文件标志判断阻塞或非阻塞操作的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、开发环境

1、内核:Linux 2.6.22.6;

2、JZ2440

3、ubuntu 9.10


二、互斥

为了实现同一时绝对的只能有一个进程使用某个设备需要互斥机制,linux互斥机制有多种,如原子变量、互斥锁、信号量、自旋锁、读写锁等等。

1、原子操作。指执行的过程中不会被别的代码路径所中断的操作。实现原子操作过程:

 1.1 其常使用的函数有:

static atomic_t canopen = ATOMIC_INIT(1); //定义原子变量并初始化为1

atomic_dec_and_test(atomic_t *v))//自减操作,并检测是否为0,为0返回ture,为1返回false。

atomic_read(atomic_t *v);//读取

atomic_dec(atomic_t *v);//自减1

atomic_inc(atomic_t *v);//自增1

 1.2 使用过程

 (1)设置原子变量。用来标记设备是否被占用。如定义原子变量canopen:

   static atomic_t canopen = ATOMIC_INIT(1);     //定义原子变量并初始化为1

 (2)在打开设备之前先测试设备是否可用。假设我们用1表示可用,检测函数如下。设备可用时,原子变量减1后为0,检测函数返回ture,非ture为false,则不执行if语句,此时原子变量也变为0,表示设备不可用。下面就可也写使用设备的函数了。

if (!atomic_dec_and_test(&canopen))   //检测,设备不可用执行if语句
{
atomic_inc(&canopen);    //将原子变量变回原来的值
return -EBUSY;
}

(3)在关闭设备的函数里最后把设备标记为未被占用。即使用atomic_inc(atomic_t *v),让原子变量为1,表示设备可用。

使用原子变量,在原子变量加减的时候,不能其他操作打断,因而保证了绝对互斥,同一时间设备只能被一个进程使用。


2、信号量

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

只有获取到信号量的进程才能打开设备,获取不到信号量的进程返回或休眠。

 2.1 使用函数

定义信号量sem

struct semaphore sem;
初始化信号量
void sema_init (struct semaphore *sem, int val);
void init_MUTEX(struct semaphore *sem); //初始化为0 

可用使用DECLARE_MUTEX,实现信号量的定义并初始化,如:DECLARE_MUTEX(name);  //定义一个信号量name,并初始化它的值为1。 

注意init_MUTEX(),DECLARE_MUTEX 在linux2.6.38以后已被移除。其中DECLARE_MUTEX(name)被DEFINE_SEMAPHORE替代,为避免与DEFINE_MUTEX 互斥锁相近引起开发者误解。

获得信号量
void down(struct semaphore * sem);
int down_interruptible(struct semaphore * sem);   //获取不到休眠,可被中断
int down_trylock(struct semaphore * sem);      //获取不到立即返回
释放信号量
void up(struct semaphore * sem);

2.2 使用过程

(1)定义一个信号量。如,定义一个信号量button_lock:

static DECLARE_MUTEX(button_lock);     //定义互斥锁

(2)打开设备时先获得信号量。如,

down(&button_lock);

也可用其他函数。第一个进程执行到down函数时可以申请到信号量button_lock,第二个进程如果再申请则申请不到,进入休眠状态,直到信号量被释放,第二个进程就可以进行

(3)关闭设备最后释放信号量。如,

  up(&button_lock);


3、阻塞、非阻塞的实现

3.1 阻塞操作,是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作。被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足。
  非阻塞操作,进程在不能进行设备操作时并不挂起,它或者放弃,或者不停地查询,直至可以进行操作为止。
 

3.2 通过判断函数带入的参数file的file->f_flags来判断是否为阻塞,以做相应的操作。

         if (file->f_flags & O_NONBLOCK)
    {
  //非阻塞,实现立即返回
    }
   else
   {
//阻塞,实现休眠

   }

实现后,应用程序调用实现后的函数时,可以选择阻塞或非阻塞方式,阻塞时陷入休眠,非阻塞时立即返回信息。一般默认是阻塞,应用程序设置非阻塞方式打开使用O_NONBLOCK,如下

    fd = open("...", O_RDWR | O_NONBLOCK);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值