在 Linux 上,我使用 shmget 和 shmat 设置一个共享内存段,一个进程将写入该段,一个或多个进程将从中读取。共享的数据大小为几兆字节,更新时将完全重写;它永远不会部分更新。
我的共享内存段布局如下:
-------------------------
| t0 | actual data | t1 |
-------------------------
其中 t0 和 t1 是编写器开始更新时间的拷贝(具有足够的精度,以便保证连续更新具有不同的时间)。 writer首先写入t1,然后复制数据,然后写入t0。另一方面,阅读器读取 t0,然后是数据,然后是 t1。如果读取器在 t0 和 t1 上获得相同的值,则它认为数据一致且有效,否则,它会重试。
此过程是否确保如果读者认为数据有效,那么它实际上就是有效的?
我需要担心乱序执行 (OOE) 吗?如果是这样,读者是否可以使用 memcpy 获取整个共享内存段来克服读者端的 OOE 问题? (这假设 memcpy 执行线性复制并通过地址空间升序。该假设是否有效?)
最佳答案
现代硬件实际上不是顺序一致的。因此,如果您不在适当的位置执行内存屏障,则不能保证这样工作。需要障碍是因为该体系结构实现了比顺序一致性更弱的共享内存一致性模型。这本身与流水线或 OoO 无关,但与允许多个处理器有效地并行访问内存系统有关。参见例如Shared memory consistency models: A tutorial .在单处理器上,您不需要障碍,因为所有代码都在该处理器上按顺序执行。
此外,不需要有两个时间字段,序列计数可能是更好的选择,因为无需担心两次更新是否非常接近以至于它们获得相同的时间戳,并且更新计数器要快得多比获取当前时间。此外,时钟不可能及时倒退,这可能会发生,例如当 ntpd 调整时钟漂移时。虽然最后一个问题可以在 Linux 上通过使用 clock_gettime(CLOCK_MONOTONIC, ...) 来解决。使用序列计数器而不是时间戳的另一个优点是您只需要一个序列计数器。写入器在写入数据之前和写入完成后都会递增计数器。然后读取器读取序列号,检查它是否是偶数,如果是,则读取数据,最后再次读取序列号并与第一个序列号进行比较。如果序号为奇数,表示正在进行写入,不需要读取数据。
Linux 内核使用一个名为 seqlocks 的锁定原语。做类似上面的事情。如果不怕“GPL污染”,可以google实现;因此这很微不足道,但诀窍在于正确设置障碍。
关于c++ - 可以在没有互斥锁的情况下读取和验证共享内存吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2555022/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re