原子操作(Atomic Operation)

本文深入探讨了Unix系统中原子操作的概念及其重要性,特别是在多进程/多线程环境下的应用场景。文章通过具体示例说明了如何利用O_APPEND标志来确保文件写入操作的原子性,并解释了在使用此标志时,lseek对write操作的影响。
Unix系统编程中的原子操作类似于数据库中事务的概念,一个操作可以由许多个步骤组成,这些步骤要么全部完成,要么不执行。
在Unix中,所有的(内核级别的???)系统调用都是原子操作,非原子的操作在多进程/多线程环境中一个典型的问题如多个进程同时向一个打开的文件写数据,早期的Unix系统open函数不支持O_APPEND,一个进程想向文件中添加数据时,典型的写法是
if(lseek(fd, 0L, 2) < 0)
err_sys("lseek error");
if(write(fd,buf,100) != 100)
err_sys("write error");

这样的写法在单进程环境下没有问题,但是在多进程的时候就有可能出现问题。因为内核有可能在进程A执行了lseek还没执行write的时候调度进程B(详细解释在APUE3.11)
所以在open文件的时候加入O_APPEND,每次write调用时,在写入数据之前内核会首先将该进程指向的文件表中的file status flags指向EOF,即写入文件末尾这个操作是一个原子操作。

问题:
如果一个文件用open("file",O_RDWR | O_APPEND)打开,可以使用lseek来进行任意的read和write么?
read可以,write不行,因为使用lseek将当前的file status flags定位到任意地方之后,在write操作执行之前,由于O_APPEND,内核会重新将标志置为EOF.所以lseek此时对write失效。
原子操作Atomic Operation)是指在多线程或并发环境中,不会被其他线程或进程打断的操作,这些操作在执行过程中是不可中断的,从而保证了对共享资源访问的完整性和一致性。原子操作与进程同步和互斥密切相关,它们都是为了保证在多线程或多处理器环境下对共享资源的安全访问,但在工作原理、适用场景以及性能特点各有不同 [^1][^2]。 ### 与进程同步和互斥的关系 原子操作是实现进程同步和互斥的一种底层方法。进程同步和互斥的目的是确保多个进程或线程对共享资源的访问不会产生冲突,而原子操作通过其不可分割的特性,天然地满足了对共享资源访问的互斥性,即要么整个操作完成,要么完全不执行,避免了多个进程或线程同时修改共享资源导致的数据不一致问题,从而实现了一种基本的同步和互斥机制 [^1][^2]。 ### 工作原理 原子操作使用硬件支持的原子指令(如 test-and-set、compare-and-swap 等),这些指令由 CPU 直接提供,能够在单个指令周期内完成。在 Linux 内核中,通过 atomic_t 类型及其相关函数(如 atomic_read()atomic_set()atomic_inc() 等)来实现 [^2]。 ### 适用场景 原子操作不涉及上下文切换,对于简单的计数器或状态标记非常有效,且不会导致线程阻塞。当共享资源的操作比较简单,如对一个整型变量进行增减操作时,使用原子操作可以高效地实现同步和互斥,避免了使用更复杂的同步机制(如互斥锁)带来的性能开销 [^2]。 ### 代码示例 以下是一个简单的使用原子操作进行计数器操作的示例(以 Linux 内核代码为例): ```c #include <linux/init.h> #include <linux/module.h> #include <linux/atomic.h> // 定义一个原子变量 static atomic_t my_counter = ATOMIC_INIT(0); static int __init my_module_init(void) { // 原子增加计数器的值 atomic_inc(&my_counter); printk(KERN_INFO "Counter value after increment: %d\n", atomic_read(&my_counter)); return 0; } static void __exit my_module_exit(void) { // 原子减少计数器的值 atomic_dec(&my_counter); printk(KERN_INFO "Counter value after decrement: %d\n", atomic_read(&my_counter)); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); ``` ### 优缺点 - **优点**:原子操作不涉及上下文切换,对于简单的计数器或状态标记非常有效,且不会导致线程阻塞,性能开销小。 - **缺点**:原子操作只能处理简单的操作,对于复杂的临界区代码段或大块共享数据结构,原子操作无法满足需求,需要使用更高级的同步机制,如互斥锁 [^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值