linux 驱动中建立进程,linux驱动编写之进程独占驱动

一、描述

嵌入式开发系统中,有各种硬件资源,而有些硬件资源使用时候是需要进程独占的。也就是说,同一时刻只有一个进程允许使用这个硬件资源,其他的进程只能放弃执行或者挂起等待。在设计其对应驱动的时候,就需要做独占处理。

example:

led灯驱动,4盏LED灯,在open的时候调用驱动,对其引脚进行配置。如果没有进程独占驱动的处理机制,效果如下:

linux 驱动中建立进程,linux驱动编写之进程独占驱动_第1张图片

fba681df91df8278276ec33e7888ed3d.png

根据测试结果可以得到结论,调用了4次应用程序led_test,每一次调用open("/dev/leds", 0),都返回了一个/dev/leds的fd,fd是相同的,都是3。应用程序led_test的4次运行,都成功得到了执行,进程pid号分别为680、681、682、683。当调用open("/dev/leds", 0)时候,对应的就会调用驱动的leds_open函数,然后进行4次初始化。

所以要实现只有一个进程使用该leds驱动,就需要在驱动模块的leds_open函数动手脚,具体实现方法如下。

二、原子操作

1、定义一个全局原子变量

static atomic_t open_ability = ATOMIC_INIT(1);

2、修改drivers_open函数

static int drivers_open(struct inode *inode, struct file *file)

{if (!atomic_dec_and_test(&open_ability))

{

atomic_inc(&open_ability);return -EBUSY;

}

............

}

如果是第一次打开或者处于关闭之后未打开状态,那么可以打开,if判断为false,执行之后的open代码段;如果已经打开了,就不能打开,返回-EBUSY.

3、修改drivers_close函数

int drivers_close(struct inode *inode, struct file *file)

{

atomic_inc(&open_ability);

............return 0;

}

打开之后,关闭驱动文件,就需要释放open_ability.

4、实现思路总结

通过引入一个变量open_ability,为硬件驱动设计一个锁,只允许一个进程对其独占;当进程使用完驱动之后,就可以释放这个资源,以提供给其他应用程序来使用。

5、测试效果

2037fa5cdddb07febe21e0f193e54e1b.png

可以看到第一次打开驱动成功,但是第二次打开驱动失败了。而且,这种方法实现的效果是,直接由驱动程序返回打开失败的消息-EBUSY.

三、信号量--互斥锁

1、定义一个互斥锁,并将互斥锁初始值设为1

static DECLARE_MUTEX(leds_lock); //利用宏来实现定义,并初始化

2、修改drivers_open函数

static int drivers_open(struct inode *inode, struct file *file)

{/*获取信号量,如果没有获得,那么就进入睡眠状态*/down(&leds_lock);

............

}

3、修改drivers_close函数

int drivers_close(struct inode *inode, struct file *file)

{

............

up(&leds_lock);return 0;

}

4、实现思路总结

利用互斥锁,来实现对硬件驱动的独占,显然是很适合的,因为互斥锁设计的初衷就是来解决这类问题。

5、测试效果

linux 驱动中建立进程,linux驱动编写之进程独占驱动_第2张图片

可以看到第一次成功打开了驱动,第二次进入了不可中断的休眠状态。也就是说,当pid号645的应用程序led_test调用调用open("/dev/leds", 0)时候,驱动程序中的down(leds_lock)令进程进入了不可中断的休眠状态,直到第一次运行pid号644的应用程序led_test释放互斥锁,才能够重新得到运行。

linux 驱动中建立进程,linux驱动编写之进程独占驱动_第3张图片

备注:STAT一栏中的,S代表“休眠状态”;D代表“不可中断的休眠状态”。

6、与原子操作实现的区别

原子操作,当第二次打开驱动文件的时候,直接返回-EBUSY,也就是说是非阻塞的;而互斥锁的这种方法,当第二次打开驱动文件的时候,由驱动程序中的down()函数迫使进程进入不可中断的休眠状态,可以说是阻塞的。

不过,如果将down()函数换成down_trylock()函数,实现的效果也是非阻塞的。

参考资料:韦东山linux视频教程

你可能感兴趣的:(linux,驱动中建立进程)