原子操作的问题

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
  • 打赏
  • 举报
回复
用信号量?

23,125

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧