设为首页 收藏本站
查看: 574|回复: 0

[经验分享] linux内核原子操作

[复制链接]

尚未签到

发表于 2018-5-17 10:38:33 | 显示全部楼层 |阅读模式
1、基本概念
原子操作可以保证指令以原子的方式执行,执行过程不被打断。它通过把读取和修改变量的行为包含在一个单步中执行,从而防止了竞争的发生,保证操作结果总是一致的。
例如:
int i=9;
线程1:
i++
i=9 OR i=8
线程2
i–;
i=9 OR i=8
两个线程并发的执行,导致结果不确定性。原子操作的作用和信号量机制是一样,都是为了防止同时访问临界资源,保证结果的一致性。大多数硬件体系结构要么本来就支持简单的原子操作,要么就为音频执行提供了锁内在总线的指令,例如x86平台上,就支持CPU锁总线操作,汇编指令前缀“LOCK”就可以将总线锁作,直到指令结束时锁打开;而有些硬件体系结构本身就不太支持原子操作,比如SPARC,但是Linux内核通过一些方法,做到了原子操作。
原子操作在Linux内核里分为原子整数操作和原子位操作,下面我们来看看这两个操作用法。

2、原子整数操作

针对整数的原子操作只能对atomic_t类型的数据进行处理,之所以没有用C语言的int类型,主要有两个原因:
1、让原子函数只接受atomic_t类型的操作数,可以确保原子操作只与这种特殊类型数据一起使用,防止该类型数据不会传给其它非原子操作
2、使用atomic_t类型确保编译器不对相应的值进行访问优化
3、在不同体系结构上实现原子操作的时候,使用atomic_t可以屏蔽其间的差异。
尽管Linux的整型数据都是32位的,但是使用atomic_t的代码只能将将该类型的数据当作24位来用,我们看看atomic_t的数据
|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
|      带符号24位整形数据        |   锁   |
|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
|10987654321098765432109876543210|
| 3         2         1          |
|            32位atmoic_t         |
|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
我们看到atomic_t中嵌入了一个8bit的锁,因为SPARC体系结构对原子操作缺乏指令级的支持,所以只能使用利用该锁来避免对原子类型数据的并发访问,对于原子操作的使用,看下面例子:
int a=3;
atomic_t v=ATOMIC_INIT(a);
atomic_add(&v,a);
atomic_inc(&v);在上面例子中,我们先定义并初始化了一个atomic_t变量,再对其进行了加法、自加操作。在Linux内核中提供了一系统的原子整数操作函数。
原子整数操作描述ATOMIC_INIT(int i)在声明一个atmoic_t变量时,将它初始化为iATOMIC_INIT(int i)在声明一个atmoic_t变量时,将它初始化为iint atmoic_read(atmoic_t *v)原子地读取整数变量vvoid atmoic_set(atmoic_t *v,int i)原子地设置v值为ivoid atmoic_add(atmoic_t *v,int i)原子地从v值加ivoid atmoic_sub(atmoic_t *v,int i)原子地从v值减ivoid atmoic_inc(atmoic_t *v)原子地从v值加1void atmoic_dec(atmoic_t *v)原子地从v值减1int atmoic_sub_and_test(int i,atmoic_t *v)原子地从v值减i,如果结果等于0返回真,否则返回假int atmoic_add_negative(int i,atmoic_t *v)原子地从v值减i,如果结果是负数返回真,否则返回假int atmoic_dec_and_test(atmoic_t *v)原子地给v减1,如果结果等于0返回真,否则返回假int atmoic_inc_and_test(atmoic_t *v)原子地给v加1,如果结果等于0返回真,否则返回假原子操作最常见的用途就是实现计数器,使用复杂的锁机制来保护一个单纯的计数是很笨拙的,原子操作比起复杂的同步方法来说,给系统带来的开销小,对高速缓存行的影响也小。

3、原子位操作

除了原子整数操作外,内核还提供了一组针对位这一级数据进行操作的函数,位操作函数是对普通的内在地址进行操作的,它的参数是一个指针和一个位号。由于是对普通的指针进程操作,所以没有像atomic_t这样的类型约束。
unsigned long word = 0;
set_bit(0,&word);
clear_bit(0,&word);
change_bit(0,&word);//翻转第0位的值原子整数操作描述void set_bit(int nr,void *addr)原子地设置addr所指对象的第nr位void clear_bit(int nr,void *addr)原子地清空addr所指对象的第nr位void change_bit(int nr,void *addr)原子地翻转addr所指对象的第nr位int test_and_set_bit(int nr,void *addr)原子地设置addr所指对象的第nr位,并返回原先的值int test_and_clear_bit(int nr,void *addr)原子地清空addr所指对象的第nr位,并返回原先的值int test_and_change_bit(int nr,void *addr)原子地翻转addr所指对象的第nr位,并返回原先的值int test_bit(int nr,void *addr)原子地返回addr所指对象的第nr位  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-461257-1-1.html 上篇帖子: Linux相关图解随记 下篇帖子: LINUX软硬链接小结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表