位原子操作

一、理论:

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 清除位

  1.  //将addr的第nr(nr为0-31)位置值置为1;  
  2.         //nr大于31时,把高27的值做为当前地址的偏移,低5位的值为要置为1的位数  
  3. extern __inline__ int set_bit(int nr,int * addr)  
  4. {      
  5. int mask, retval;         
  6. addr += nr >> 5;                 //nr大于31时,把高27的值做为当前地址的偏移,      
  7. mask = 1 << (nr & 0x1f);         //获取31范围内的值,并把1向左偏移该位数      
  8. *addr |= mask;       sti();                           //开所有中断      
  9. cli();                           //关所有中断      
  10. retval = (mask & *addr) != 0;    //位置置1      
  11. //nr大于31时,把高27的值做为当前地址的偏移,低5位的值为要置为0的位数;  
  12. return retval;                   //返回置数值  
  13. }     
  14.        
  15.          //将addr的第nr(nr为0-31)位置值置为0;  
  16. extern __inline__ int clear_bit(int nr, int * addr)  
  17. retval = (mask & *addr) != 0;      
  18. {      
  19. int mask, retval;         
  20. addr += nr >> 5;      
  21. mask = 1 << (nr & 0x1f);      
  22. cli();      
  23. *addr &= ~mask;      
  24. extern __inline__ int test_bit(int nr, int * addr)  
  25. sti();      
  26. return retval;  
  27. }     
  28. //判断addr的第nr(nr为0-31)位置的值是否为1;  
  29. //nr大于31时,把高27的值做为当前地址的偏移,低5位的值为要判断的位数;  
  30.         extern __inline__ int test_bit(int nr, int * addr)  
  31. {      
  32. int mask;         
  33. addr += nr >> 5;      
  34. mask = 1 << (nr & 0x1f);      
  35. return ((mask & *addr) != 0);  
  36. }
三、实例

1、驱动程序

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. /*驱动注册的头文件,包含驱动的结构体和注册和卸载的函数*/
  4. #include <linux/platform_device.h>
  5. /*注册杂项设备头文件*/
  6. #include <linux/miscdevice.h>
  7. /*注册设备节点的文件结构体*/
  8. #include <linux/fs.h>
  9. //原子操作的函数头文件
  10. #include <asm/atomic.h>
  11. #include <asm/types.h>
  12. #define DRIVER_NAME "atomic_bit"
  13. #define DEVICE_NAME "atomic_bit"
  14. MODULE_LICENSE("Dual BSD/GPL");
  15. MODULE_AUTHOR("TOPEET");
  16. //定义原子变量,并初始化为0
  17. //static atomic_t value_atomic = ATOMIC_INIT(0);
  18. unsigned long int value_bit = 0;
  19. static int atomic_bit_open(struct inode *inode, struct file *file){
  20. printk(KERN_EMERG "atomic_bit open in!\n");
  21. /*if(atomic_read(&value_atomic)){
  22. return -EBUSY;
  23. }*/
  24. //atomic_inc(&value_atomic);
  25. if(test_bit(0,&value_bit)!=0){
  26. return -EBUSY;
  27. }
  28. set_bit(0,&value_bit);
  29. printk(KERN_EMERG "atomic_bit open success!\n");
  30. return 0;
  31. }
  32. static int atomic_bit_release(struct inode *inode, struct file *file){
  33. printk(KERN_EMERG "atomic_bit release\n");
  34. clear_bit(0,&value_bit);
  35. //atomic_dec(&value_atomic);
  36. return 0;
  37. }
  38. static struct file_operations atomic_bit_ops = {
  39. .owner = THIS_MODULE,
  40. .open = atomic_bit_open,
  41. .release = atomic_bit_release,
  42. };
  43. static struct miscdevice atomic_bit_dev = {
  44. .minor = MISC_DYNAMIC_MINOR,
  45. .name = DEVICE_NAME,
  46. .fops = &atomic_bit_ops,
  47. };
  48. static int atomic_bit_probe(struct platform_device *pdv){
  49. printk(KERN_EMERG "\tinitialized\n");
  50. misc_register(&atomic_bit_dev);
  51. return 0;
  52. }
  53. static int atomic_bit_remove(struct platform_device *pdv){
  54. printk(KERN_EMERG "\tremove\n");
  55. misc_deregister(&atomic_bit_dev);
  56. return 0;
  57. }
  58. struct platform_driver atomic_bit_driver = {
  59. .probe = atomic_bit_probe,
  60. .remove = atomic_bit_remove,
  61. .driver = {
  62. .name = DRIVER_NAME,
  63. .owner = THIS_MODULE,
  64. }
  65. };
  66. static int atomic_bit_init(void)
  67. {
  68. int DriverState;
  69. printk(KERN_EMERG "HELLO WORLD enter!\n");
  70. DriverState = platform_driver_register(&atomic_bit_driver);
  71. printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
  72. return 0;
  73. }
  74. static void atomic_bit_exit(void)
  75. {
  76. printk(KERN_EMERG "HELLO WORLD exit!\n");
  77. platform_driver_unregister(&atomic_bit_driver);
  78. }
  79. module_init(atomic_bit_init);
  80. module_exit(atomic_bit_exit);

2、测试程序


 
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <sys/ioctl.h>
  7. #include <errno.h>
  8. int main(int argc,char **argv){
  9. char *atomic_bit = "/dev/atomic_bit";
  10. int fd1;
  11. if((fd1 = open(atomic_bit,O_RDWR|O_NDELAY))==0){
  12. printf("%s open %s success\n",argv[0],atomic_bit);
  13. }
  14. else{
  15. perror(argv[0]);
  16. }
  17. while(1);
  18. close(fd1);
  19. }
  20. #include <stdio.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <sys/ioctl.h>
  26. #include <errno.h>
  27. int main(int argc,char **argv){
  28. char *atomic_bit = "/dev/atomic_bit";
  29. int fd1;
  30. if((fd1 = open(atomic_bit,O_RDWR|O_NDELAY))==0){
  31. printf("%s open %s success!\n",argv[0],atomic_bit);
  32. }
  33. else{
  34. perror(argv[0]);
  35. }
  36. while(1);
  37. close(fd1);
  38. }




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值