一、理论:
1.并发并发的概念是:多个执行单元同时、并行被执行。
Linux系统是多任务的,很多任务会同时执行。
假如有三个执行单元ABC,共享了内存资源。
执行单元A对Buffer写1000个“a”;
执行单元B对Buffer写1000个“b”;
执行单元C从buffer中读取数据。
如果按照A写→C读→B写→C读,当然没有问题。
但是如果A写→B写→C读,执行单元C就出问题了。
当然比这个复杂更多,更加混乱的并发操作存在设备驱动中,
只要有多个进程对共享资源的同时访问,就可能出现竞态。
2.竞态
以下三种情况会导致竞态。
对称多处理的多个CPU
单CPU内进程和抢占它的进程
中断和进程
3.竞态的解决方法
解决竞态的途径是“保证对共享资源的互斥访问”
也就是一个执行单元在访问共享资源的时候,其它的执行单元被禁止访问。
访问共享资源的代码区称为临界区,临界区需要使用互斥机制来保护。
4.Linux操作系统中提供实现互斥的方法:
原子操作、自旋锁、信号量、互斥体等。
我们后续的视频介绍原子操作,自旋锁,互斥体
二、函数
1.直接列出内核中提供的宏定义宏定义:test_bit 返回位原子值
宏定义:set_bit 设置位
宏定义:clear_bit 清除位
//将addr的第nr(nr为0-31)位置值置为1;
//nr大于31时,把高27的值做为当前地址的偏移,低5位的值为要置为1的位数
extern __inline__ int set_bit(int nr,int * addr)
{
int mask, retval;
addr += nr >> 5; //nr大于31时,把高27的值做为当前地址的偏移,
mask = 1 << (nr & 0x1f); //获取31范围内的值,并把1向左偏移该位数
*addr |= mask; sti(); //开所有中断
cli(); //关所有中断
retval = (mask & *addr) != 0; //位置置1
//nr大于31时,把高27的值做为当前地址的偏移,低5位的值为要置为0的位数;
return retval; //返回置数值
}
//将addr的第nr(nr为0-31)位置值置为0;
extern __inline__ int clear_bit(int nr, int * addr)
retval = (mask & *addr) != 0;
{
int mask, retval;
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
cli();
*addr &= ~mask;
extern __inline__ int test_bit(int nr, int * addr)
sti();
return retval;
}
//判断addr的第nr(nr为0-31)位置的值是否为1;
//nr大于31时,把高27的值做为当前地址的偏移,低5位的值为要判断的位数;
extern __inline__ int test_bit(int nr, int * addr)
{
int mask;
addr += nr >> 5;
mask = 1 << (nr & 0x1f);
return ((mask & *addr) != 0);
}
三、实例
1、驱动程序
- #include <linux/init.h>
- #include <linux/module.h>
- /*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
- #include <linux/platform_device.h>
- /*注册杂项设备头文件*/
- #include <linux/miscdevice.h>
- /*注册设备节点的文件结构体*/
- #include <linux/fs.h>
- //原子操作的函数头文件
- #include <asm/atomic.h>
- #include <asm/types.h>
- #define DRIVER_NAME "atomic_bit"
- #define DEVICE_NAME "atomic_bit"
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_AUTHOR("TOPEET");
- //定义原子变量,并初始化为0
- //static atomic_t value_atomic = ATOMIC_INIT(0);
- unsigned long int value_bit = 0;
- static int atomic_bit_open(struct inode *inode, struct file *file){
- printk(KERN_EMERG "atomic_bit open in!\n");
- /*if(atomic_read(&value_atomic)){
- return -EBUSY;
- }*/
- //atomic_inc(&value_atomic);
- if(test_bit(0,&value_bit)!=0){
- return -EBUSY;
- }
- set_bit(0,&value_bit);
- printk(KERN_EMERG "atomic_bit open success!\n");
- return 0;
- }
- static int atomic_bit_release(struct inode *inode, struct file *file){
- printk(KERN_EMERG "atomic_bit release\n");
- clear_bit(0,&value_bit);
- //atomic_dec(&value_atomic);
- return 0;
- }
- static struct file_operations atomic_bit_ops = {
- .owner = THIS_MODULE,
- .open = atomic_bit_open,
- .release = atomic_bit_release,
- };
- static struct miscdevice atomic_bit_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &atomic_bit_ops,
- };
- static int atomic_bit_probe(struct platform_device *pdv){
- printk(KERN_EMERG "\tinitialized\n");
- misc_register(&atomic_bit_dev);
- return 0;
- }
- static int atomic_bit_remove(struct platform_device *pdv){
- printk(KERN_EMERG "\tremove\n");
- misc_deregister(&atomic_bit_dev);
- return 0;
- }
- struct platform_driver atomic_bit_driver = {
- .probe = atomic_bit_probe,
- .remove = atomic_bit_remove,
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
- }
- };
- static int atomic_bit_init(void)
- {
- int DriverState;
- printk(KERN_EMERG "HELLO WORLD enter!\n");
- DriverState = platform_driver_register(&atomic_bit_driver);
- printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
- return 0;
- }
- static void atomic_bit_exit(void)
- {
- printk(KERN_EMERG "HELLO WORLD exit!\n");
- platform_driver_unregister(&atomic_bit_driver);
- }
- module_init(atomic_bit_init);
- module_exit(atomic_bit_exit);
2、测试程序
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <errno.h>
- int main(int argc,char **argv){
- char *atomic_bit = "/dev/atomic_bit";
- int fd1;
- if((fd1 = open(atomic_bit,O_RDWR|O_NDELAY))==0){
- printf("%s open %s success\n",argv[0],atomic_bit);
- }
- else{
- perror(argv[0]);
- }
- while(1);
- close(fd1);
- }
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <errno.h>
- int main(int argc,char **argv){
- char *atomic_bit = "/dev/atomic_bit";
- int fd1;
- if((fd1 = open(atomic_bit,O_RDWR|O_NDELAY))==0){
- printf("%s open %s success!\n",argv[0],atomic_bit);
- }
- else{
- perror(argv[0]);
- }
- while(1);
- close(fd1);
- }