社区
Linux/Unix社区
帖子详情
原子操作的问题
970361
2003-08-27 03:42:40
我想在用户空间执行原子操作,请问给如何实现啊?
...全文
180
11
打赏
收藏
原子操作的问题
我想在用户空间执行原子操作,请问给如何实现啊?
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
11 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
970361
2003-09-02
打赏
举报
回复
to : CoolQ() ( )
"上边你列出的就是SysV IPC的信号量,也算是原子操作吧。"
〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉
while(((semop_ret=semop(semid,&semwait,1))==-1)&&(errno==EINTR));
while(*c!='\0')fputc(*c++,stderr); /* 这里是原子操作吗???*/
while(((semop_ret=semop(semid,&semsignal,1))==-1)&&(errno==EINTR));
wabc
2003-08-29
打赏
举报
回复
pthread中不是有原子操作的函数吗
CoolQ
2003-08-29
打赏
举报
回复
不知道你是用什么CPU?UNP还是SMP?IA还是别的体系?
上边你列出的就是SysV IPC的信号量,也算是原子操作吧。
你说的原子操作也很含糊,你是想把一个数加到另一个变量上,一次性完成,所以不想用信号量还是别的?我不知道lock指令在80x86上算不算特权指令,如果不是的话,你在用户态SMP也是可以使用的。
以下是内核源代码:
#ifdef CONFIG_SMP
#define LOCK "lock ; "
#else
#define LOCK ""
#endif
typedef struct { volatile int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
static __inline__ void atomic_add(int i, atomic_t *v)
{
__asm__ __volatile__(
LOCK "addl %1,%0"
:"=m" (v->counter)
:"ir" (i), "m" (v->counter));
}
感觉这个函数在80x86 UNP 上和 n += i;没有什么区别,只是用__volatile__来拒绝编译器的优化,但是在SMP上多了一个lock指令。
970361
2003-08-29
打赏
举报
回复
我看到很多地方是这么用的,可是不知道到底是不是原子操作,这个东西又不怎么好测试
不知道哪位高手有没有这样用过??
/*******************************************/
#define PERMS S_IRUSR|S_IWUSR
void init_semaphore_struct(struct sembuf *sem,int semnum,
int semop,int semflg)
{
/* 初始话信号灯结构 */
sem->sem_num=semnum;
sem->sem_op=semop;
sem->sem_flg=semflg;
}
int del_semaphore(int semid)
{
/* 信号灯并不随程序的结束而被删除,如果我们没删除的话(将1改为0)
可以用ipcs命令查看到信号灯,用ipcrm可以删除信号灯的
*/
#if 1
return semctl(semid,0,IPC_RMID);
#endif
}
int main(int argc,char **argv)
{
char buffer[MAX_CANON],*c;
int i,n;
int semid,semop_ret,status;
pid_t childpid;
struct sembuf semwait,semsignal;
if((argc!=2)||((n=atoi(argv[1]))<1))
{
fprintf(stderr,"Usage:%s number\n\a",argv[0]);
exit(1);
}
/* 使用IPC_PRIVATE 表示由系统选择一个关键字来创建 */
/* 创建以后信号灯的初始值为0 */
if((semid=semget(IPC_PRIVATE,1,PERMS))==-1)
{
fprintf(stderr,"[%d]:Acess Semaphore Error:%s\n\a",
getpid(),strerror(errno));
exit(1);
}
/* semwait是要求资源的操作(-1) */
init_semaphore_struct(&semwait,0,-1,0);
/* semsignal是释放资源的操作(+1) */
init_semaphore_struct(&semsignal,0,1,0);
/* 开始的时候有一个系统资源(一个标准错误输出) */
if(semop(semid,&semsignal,1)==-1)
{
fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",
getpid(),strerror(errno));
if(del_semaphore(semid)==-1)
fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",
getpid(),strerror(errno));
exit(1);
}
/* 创建一个进程链 */
for(i=0;i if(childpid=fork()) break;
sprintf(buffer,"[i=%d]-->[Process=%d]-->[Parent=%d]-->[Child=%d]\n",
i,getpid(),getppid(),childpid);
c=buffer;
/* 这里要求资源,进入原子操作 */
while(((semop_ret=semop(semid,&semwait,1))==-1)&&(errno==EINTR));
if(semop_ret==-1)
{
fprintf(stderr,"[%d]:Decrement Semaphore Error:%s\n\a",
getpid(),strerror(errno));
}
else
{
while(*c!='\0')fputc(*c++,stderr);
/* 原子操作完成,赶快释放资源 */
while(((semop_ret=semop(semid,&semsignal,1))==-1)&&(errno==EINTR));
if(semop_ret==-1)
fprintf(stderr,"[%d]:Increment Semaphore Error:%s\n\a",
getpid(),strerror(errno));
}
/* 不能够在其他进程反问信号灯的时候,我们删除了信号灯 */
while((wait(&status)==-1)&&(errno==EINTR));
/* 信号灯只能够被删除一次的 */
if(i==1)
if(del_semaphore(semid)==-1)
fprintf(stderr,"[%d]:Destroy Semaphore Error:%s\n\a",
getpid(),strerror(errno));
exit(0);
}
970361
2003-08-29
打赏
举报
回复
那是在内核中使用的啊
970361
2003-08-29
打赏
举报
回复
我需要的原子操作是对链表的增加和删除,而不是简单的将标志增加或者减少
970361
2003-08-29
打赏
举报
回复
因为我写的程序不是针对特定的硬件平台,可能是P4也可能是xeon或者是别的。也不是运行在内核态的,所以不能使用汇编。
我的程序中有一链表是公共数据,其中可能增加或者是减少链表中的一个接点,这个操作由一个特定的线程来完成,这个操作的频率非常低,其他现成来读这个公共链表,有的操作会非常的慢,因为要读数据库,也要等待网络。所以我只好放在其他线程。但是成个程序的性能要求太高,响应必须非常的及时。我只是想在对链表的删除或者增加接点的时候保证是原子的,避免过多的互斥,因为我理论计算的记过互斥操作会站用20%左右的资源,这样多线程带来的好出就被抵消了,而且增加了复杂程度。
要是在对链表的增加和删除的关键地方能够实现原子操作那么程序就可以简单很多,而且效率上也提高不少。
CoolQ
2003-08-28
打赏
举报
回复
应该是可以,你可以参看内核里的/usr/src/linux-2.4/include/asm-i386/atomic.h
里边有相应的函数,大部分都是一些汇编
970361
2003-08-28
打赏
举报
回复
谁能帮忙吗
970361
2003-08-27
打赏
举报
回复
是的,我考虑过用信号量,但是那样太复杂,如果有个原子操作可以完成的话,那样会非常简单,内核中是可以使用的,但是我不知道,在用户空间如何实现
CoolQ
2003-08-27
打赏
举报
回复
用信号量?
2023最新,最全,最细的JUC多线程并发教程
在并发应用中就就会全面的带你们分析 JUC 包中的源码了,具体会分析下面这些:
原子操作
类中的所有类源码,包括 XXXAccumulator 、 XXXAdder 锁相关,包括 AQS 所有源码、Condition 条件源码、ReentrantLock 、...
Qt里的
原子操作
所谓
原子操作
,即一系列复杂的操作能一气呵成,中间不被其他的操作打断。这在多线程程序中尤其常见,但要实现这种功能,既要考虑程序的良好设计,又要关心特定平台的体系结构和相关编译器对原子特性的支持程度。所以,为了简化这个过程,Qt为我们提供了QAtomicInteger模板类,该类封装了大量与
原子操作
相关的细节和底层特性,为我们提供了方便易用的上层接口。虽然,该类并不能解决所有的
原子操作
问题
,比如在不同
linux中关于
原子操作
原子操作
:就是在执行某一操作时不被打断。 linux
原子操作
问题
来源于进程的抢占以及多核smp系统中程序的并发执行。 对于临界区的操作可以加锁来保证原子性,对于全局变量或静态变量操作则需要依赖于硬件平台的原子变量操作。 因此
原子操作
有两类:一类是各种临界区的锁,一类是操作原子变量的函数。 对于arm来说,单核每条汇编指令都是原子的,多核smp也是,因为有总线仲裁所以cpu可以单独占用总线直
高性能编程——线程安全
问题
之
原子操作
文章目录原子性
问题
原子操作
问题
产生的原因 原子性
问题
其实多线程就只有两个重要的
问题
,一个是可见性
问题
,另一个则是原子性
问题
了。本章将会着重讲原子性
问题
。
原子操作
上面说到了的原子性
问题
究竟是什么?先看两段代码和输出结果就知道了。 public class Counter { volatile int i = 0 ; public void add(){ i++...
什么是
原子操作
?
什么是
原子操作
?
原子操作
:就是在执行某一操作时不被打断。 Linux
原子操作
问题
来源于中断、进程的抢占以及多核smp系统中程序的并发执行。 对于临界区的操作可以加锁来保证原子性,对于全局变量或静态变量操作则需要依赖于硬件平台的原子变量操作。 因此
原子操作
有两类:一类是各种临界区的锁,一类是操作原子变量的函数。 对于arm来说,单条汇编指令都是原子的,多核smp也
Linux/Unix社区
23,125
社区成员
74,509
社区内容
发帖
与我相关
我的任务
Linux/Unix社区
Linux/Unix社区 应用程序开发区
复制链接
扫一扫
分享
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章