免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: Moon_Bird
打印 上一主题 下一主题

[C] 面试题:一个进程读,一个进程写,怎么实现无锁访问共享内存呢 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2012-10-01 16:14 |只看该作者
回复 9# linux_c_py_php

pthread是线程库,不是进程间的
   

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
12 [报告]
发表于 2012-10-01 16:25 |只看该作者
没有读过APUE, 没有做过进程共享的队列吗... 基础功啊.
  1. NAME
  2.        pthread_condattr_getpshared, pthread_condattr_setpshared - get and set the process-shared condition variable attributes

  3. SYNOPSIS
  4.        #include <pthread.h>

  5.        int pthread_condattr_getpshared(const pthread_condattr_t *restrict attr,
  6.               int *restrict pshared);
  7.        int pthread_condattr_setpshared(pthread_condattr_t *attr,
  8.               int pshared);

  9. DESCRIPTION
  10.        The pthread_condattr_getpshared() function shall obtain the value of the process-shared attribute from the attributes object referenced by attr.
  11.        The pthread_condattr_setpshared() function shall set the process-shared attribute in an initialized attributes object referenced by attr.

  12.        The  process-shared  attribute is set to PTHREAD_PROCESS_SHARED to permit a condition variable to be operated upon by any thread that has access
  13.        to the memory where the condition variable is allocated, even if the condition variable is allocated in memory that is shared by  multiple  pro-
  14.        cesses. If the process-shared attribute is PTHREAD_PROCESS_PRIVATE, the condition variable shall only be operated upon by threads created within
  15.        the same process as the thread that initialized the condition variable; if threads of differing processes attempt to operate on such a condition
  16.        variable, the behavior is undefined. The default value of the attribute is PTHREAD_PROCESS_PRIVATE.

  17. RETURN VALUE
  18.        If successful, the pthread_condattr_setpshared() function shall return zero; otherwise, an error number shall be returned to indicate the error.

  19.        If successful, the pthread_condattr_getpshared() function shall return zero and store the value of the process-shared attribute of attr into the
  20.        object referenced by the pshared parameter. Otherwise, an error number shall be returned to indicate the error.
复制代码
0xC1988 发表于 2012-10-01 16:14
回复 9# linux_c_py_php

pthread是线程库,不是进程间的

论坛徽章:
0
13 [报告]
发表于 2012-10-01 16:49 |只看该作者
回复 12# linux_c_py_php

没系统的读完,基本功不扎实,承教了


   

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
14 [报告]
发表于 2012-10-01 22:02 |只看该作者
无锁队列(放到share内存中)。

其实既然是进程了,加个锁是很容易的事情。

另一个办法就是别用共享内存了。用管道吧,这个不用锁。

Google的binder是一个很好的例子。用msgqueue驱动,而shared memory仅仅是一个缓冲区而已。只读或者只写。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
15 [报告]
发表于 2012-10-02 09:23 |只看该作者
回复 14# starwing83


    题目要求用共享内存。

加锁吧。

论坛徽章:
0
16 [报告]
发表于 2012-10-02 11:08 |只看该作者
回复 9# linux_c_py_php

的确是腾讯问的.........         果然经验老到呀  呵呵  

@starwing83  所说的无锁队列应该是比较好的实现方法
http://coolshell.cn/articles/8239.html  有详细的说明


   

论坛徽章:
0
17 [报告]
发表于 2012-10-02 18:55 |只看该作者
最近刚好做了个类似的东西,用semaphore
数据缓冲区(sharememory)按块使用,一个sem是空闲快资源块数(sem1),一个sem是待读取资源块数(sem2),然后么就是实现一个循环队列了
1、初始化sem1为总块数,sem2为0,两端的读写位置(其实就是块下标)均为0
2、发送端wait sem1 ,正确返回,则memcpy数据至当前w,然后w位置++,post sem2
3、接收端wait sem2,正确返回,则从当前r中memcpy数据出来,然后r位置++,然后post sem1

PS:
所谓w/r 其实就是第几快,类似数组下标的概念,按照循环队列的实现,到了最后一块又置为0
以块来使用难免会碰到一次不能填充满整个块,所以在每一数据块前几字节专门用于记录数据长度,剩下才是数据区
如果生产大于消费,耗尽了所有块,那么直接给应用层返回缓冲区满的错误就行了(socket就这么做的)

论坛徽章:
1
技术图书徽章
日期:2014-03-06 15:32:30
18 [报告]
发表于 2012-10-02 22:43 |只看该作者
这种单独单写的连原子操作都不需要,更不要说mutex之类的了。

假设A,B两进程通信

首先,将共享内存区域分成n块,如何分自己定义。

其次,每块内存指定一个byte做标志,

         定义为: 0为A可读写状态,B不可读写;
                    1为B可读写状态,A不可读写。
A的行为:
          遍历n块内存,找到一个标志为0的:
          接收:
          查看是否有B发来的消息,有,则接收,设置为可发送状态;
          发送:消息复制到该块区域,设置标志为1;
B的行为:
          遍历n块内存,找到一个标志为1的:
          接收:
          查看是否有B发来的消息,有,则接收,设置为可发送状态;
          发送:消息复制到该块区域,设置标志为0;
         

论坛徽章:
0
19 [报告]
发表于 2012-10-03 20:58 |只看该作者
本帖最后由 一刀。 于 2012-10-03 21:33 编辑

用sched_yield()、信号、共享内存模拟线程的条件变量。
或者用共享内存模拟自旋锁。


补充一下:sched_yield()的方法只能用于单CPU环境,不需要使用信号。自旋锁的方法用google搜索Peterson方案。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
20 [报告]
发表于 2012-10-03 22:41 |只看该作者
无锁读写,当读写条件不满足时,必然用忙等来达到所需条件。
yield(),也不过对忙等做点小优化。

与其如此,还不如用锁来的实在。

逐鹿实在理解不了为什么总有人提这样的方案。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP