内核同步机制
来源:互联网 发布:数据库集群方案 编辑:程序博客网 时间:2024/05/22 07:04
linux 内核为了避免共享数据(临界区)访问冲突,提出了一些控制机制:原子量,自旋锁,信号量
原子量:
- 原子操作:cpu 执行某个操作过程中,不可被外界打断或中断
- 原子变量:原子量的运算过程不可被中断
如何使用原子变量:
1.定义原子量 :atomic_t xxx
2.原子量操作函数:
atomic_set(&v, i) //初始化atomic_read(v) //读atomic_add(int i, volatile atomic_t *v) //加,无返回值atomic_sub(int i, volatile atomic_t *v) //减,无返回值int atomic_add_return(int i, volatile atomic_t *v) //加int atomic_sub_return(int i, volatile atomic_t *v) //减int atomic_cmpxchg(atomic_t *v, int old, int new) //交换atomic_inc(v) //自加atomic_dec(v) //自减
自旋锁
如果一个进程给临界区加锁,后来的进程加速哦是加锁不成功,会发生阻塞,只到临界区被解锁,后来的进程解除阻塞,加锁成功,继续运行
如何使用自旋锁
1.定义自旋锁 :spinlock_t xxx
2.初始化自旋锁:spin_lock_init(_lock)
3.临界区前加锁:static inline void spin_lock(spinlock_t *lock)
4.临界区后解锁:static inline void spin_unlock(spinlock_t *lock)
信号量
主要用于进程间同步,本质上是一个计数器,每当进程访问共享资源时,信号量做减一操作,如果信号量为0,后来的进程在做减一操纵不成功,会发生阻塞,知道信号量大于零,才解除阻塞,减一成功,继续执行
如何使用信号量
1.定义信号量:struct semaphore xxx
2.初始化信号量:sema_init(struct semaphore *sem, int val)
3.减一操作: down(struct semaphore *sem)
4.加一操作:up(struct semaphore *sem)
示例代码:
#include <linux/kernel.h>#include <linux/module.h>#include <linux/cdev.h>#include <linux/fs.h>#include <linux/miscdevice.h>#include <linux/kdev_t.h>#include <linux/device.h>#include <linux/io.h>#include <linux/uaccess.h>#include <linux/export.h>#include <linux/types.h>#include <linux/atomic.h>#include <linux/spinlock.h>#define GPM4CON 0x110002E0volatile unsigned long *baseaddr = 0;#define rGPM4CON (*((volatile unsigned long *)(baseaddr + 0)))#define rGPM4DAT (*((volatile unsigned long *)(baseaddr + 1)))#define MYLED_MAJOR 0#define MYLED_NAME "led"#define MYLED_DRVNUM 1#define MYLED_NUM 4dev_t myled_devt; //设备号int myled_major;struct class *myled_class; //设备结构体struct cdev *myled; //设备驱动核心结构//atomic_t myled_atomic; //原子操作/*//自旋锁操作int count;struct spinlock myled_spinlock;*/struct semaphore myled_semaphore;char led_status[MYLED_NUM]={-1,-1,-1,-1};loff_t led_lseek (struct file *fp, loff_t off, int whence){ loff_t newoff=0; switch(whence) { case SEEK_SET: newoff=off; break; case SEEK_CUR: newoff = fp->f_pos+off; break; case SEEK_END: newoff = 4 + off; default: return -EINVAL; } if(newoff<0) newoff = 0; else if(newoff>4) newoff = 4; fp->f_pos=newoff; return newoff;}ssize_t led_read (struct file *fp, char __user *buf, size_t size, loff_t *off){ int i=0; unsigned long ret; if(*off>4) return -EINVAL; if(*off+size>4) size = 4-*off; for(i=0;i<MYLED_NUM;i++) led_status[i]= !(rGPM4DAT&(0x1<<i)); ret = copy_to_user(buf,&led_status[*off],size); *off = *off+size; printk("led_read is called\n"); return 0;}ssize_t led_write (struct file *fp, const char __user *buf, size_t size, loff_t *off){ int i; unsigned long temp; if(*off>4) return -EINVAL; if(*off + size >4) size = 4 - *off; temp = copy_from_user(&led_status[*off],buf,size); for(i=0;i<MYLED_NUM;i++) { if(led_status[i] == 0) rGPM4DAT |= (0x1<<i); else if(led_status[i] == 1) rGPM4DAT &= ~(0x1<<i); else return -EINVAL; } *off = *off + size; printk("led_write is called \n"); return 0;}int led_open (struct inode *node, struct file *fp){ int i=0;/* //原子操作 if(myled_atomic.counter) { printk("this derive is being used \n"); return -EINVAL; } atomic_inc(&myled_atomic);*//* //自旋锁 spin_lock(&myled_spinlock); if(count) { printk("this device is being used \n"); spin_unlock(&myled_spinlock); return -EINVAL; } count++; spin_unlock(&myled_spinlock);*/ //信号量 down(&myled_semaphore); fp->private_data =(void *) MINOR(node->i_rdev); rGPM4CON &= ~(0xffff); rGPM4CON |= (0x1111); for(i=0;i<MYLED_NUM;i++) { led_status[i] = !(rGPM4DAT&(0x1<<i)); } printk("led_open is called \n"); return 0;}int led_close (struct inode *node, struct file *fp){ printk("led_close is called \n");/* //原子操作 if(myled_atomic.counter) atomic_dec(&myled_atomic);*//* //自旋锁 spin_lock(&myled_spinlock); if(count) count--; spin_unlock(&myled_spinlock);*/ //信号量 up(&myled_semaphore); return 0;}long led_ioctl(struct file *fp, unsigned int cmd, unsigned long arg){ int i=0; if(_IOC_TYPE(cmd) != 'x') return -EINVAL; switch (_IOC_DIR(cmd)) { case _IOC_READ: for(i=0;i<MYLED_NUM;i++) { led_status[i] =! (rGPM4DAT&(0x1<<i)); } if(copy_to_user((long*)arg,led_status,4)) return -EINVAL; break; case _IOC_WRITE: if(_IOC_NR(cmd)==0) rGPM4DAT |= (0x1<<arg); else if(_IOC_NR(cmd) == 1) rGPM4DAT &= ~(0x1<<arg); else return -EINVAL; break; case (_IOC_WRITE|_IOC_READ): { for(i=0;i<MYLED_NUM;i++) led_status[i]=! (rGPM4DAT&(0x1<<i)); switch (_IOC_NR(cmd)) { case 0: rGPM4DAT |= (0x1<<*((int *)arg)); break; case 1: rGPM4DAT &= ~(0x1<<*((int *)arg)); break; default : return -EINVAL; break; } if(copy_to_user((long*)arg,led_status,MYLED_NUM)) return -EINVAL; break; } case _IOC_NONE: break; default: break; } return 0;}struct file_operations led_fops={ .owner=THIS_MODULE, .open =led_open, .release = led_close, .read=led_read, .write = led_write, .unlocked_ioctl= led_ioctl, .llseek = led_lseek,};static int __init myled_init(void){ int i=0; //原子操作// atomic_set(&myled_atomic,0);/* //自旋锁 spin_lock_init(&myled_spinlock); count=0;*/ //信号量 sema_init(&myled_semaphore,1);#if MYLED_MAJOR myled_major = MYLED_MAJOR; myled_devt = MKDEV(myled_major,0); if(register_chrdev_region(myled_devt,MYLED_DRVNUM,MYLED_NAME))#else if(alloc_chrdev_region(&myled_devt,0,MYLED_DRVNUM,MYLED_NAME))#endif { printk("注册失败\n"); return -EBUSY; } myled = cdev_alloc(); cdev_init(myled,&led_fops); if(cdev_add(myled,myled_devt,MYLED_DRVNUM)) { printk("注册成功\n"); return -EBUSY; } printk("注册成功\n"); myled_class = class_create(THIS_MODULE,MYLED_NAME); for(i=0;i<MYLED_DRVNUM;i++) device_create(myled_class,NULL,myled_devt+i,NULL,"myled%d",i); baseaddr = ioremap(GPM4CON, 8); return 0;}static void __exit myled_exit(void){ iounmap(baseaddr); device_destroy(myled_class, myled_devt); class_destroy(myled_class); cdev_del(myled); unregister_chrdev_region(myled_devt,MYLED_DRVNUM); printk("注销成功\n");}module_init(myled_init);module_exit(myled_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("MOMO");
阅读全文
0 0
- 内核同步机制-信号量
- Linux 内核同步机制
- Linux 内核同步机制
- Linux内核 - 同步机制
- 内核同步机制
- 内核同步机制-信号量
- linux内核同步机制
- Linux 内核同步机制
- 内核同步机制概述
- linux 内核同步机制
- 内核同步机制
- Linux 内核同步机制
- 内核同步机制
- 内核同步机制
- 内核同步机制
- 内核同步机制
- 内核同步机制-RCU同步机制
- Linux内核的同步机制
- rabbitmq(安装)
- 比特位操作——二进制表示
- CString分割切分 实现SplitCString
- 剑指offer-数值的整数次方
- Ubuntu 安装dbus-python 错误解决
- 内核同步机制
- POJ3660---Cow Contest(floyed传递闭包问题)
- 红黑树原理简析
- 表单数据验证
- 从互联网进化的角度看AI+时代的巨头竞争
- jsp——9大内置对象
- 输入域名到显示网页的网络过程
- Rviz教程(七):Plugins: New Display Type
- 2017暑假七林集训day8