LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1435|回复: 7

多道程序共享内存的问题

[复制链接]
发表于 2007-12-19 10:16:52 | 显示全部楼层 |阅读模式
在使用shmget()取得共享内存区域的时候,第一个参数是用户指定的key,如果另一道程序刚巧也使用

了这个key,理论上会造成冲突。即使使用ftok()来产生,也有可能对2道不相干的程序产生同样的key

。《understanding the linux kernel》也证实了这个问题的存在。
那么想请问:
1。通常linux程序员在编程的时候是采取什么方法避免这个冲突的呢?是不是有什么编程惯例之类的?
2。如果将情况简化,令访问同一个共享内存区域的线程来自同一个程序,(1)一条线程开辟共享内存,

取得shmget()的返回值IPC identifier,(2)生成子线程,并把identifier传递给子线程,(3)子线

程根据identifier访问共享内存。这样就不会产生冲突,那么如果我传递的不是identifier而是父线程的

线程号可以不?有可能实现不?

先行谢过!
发表于 2007-12-19 16:45:53 | 显示全部楼层
自己定吧
另外多线程不需要共享内存
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-12-19 18:23:20 | 显示全部楼层
Post by x11;1797580
自己定吧
另外多线程不需要共享内存

此话怎讲?
共享内存是为了传递消息,传递消息是否有必要取决于程序员的编程意图,
比如在生产者-消费者模型上,不可能不传递消息的啊
不知道老兄说不需要共享内存是什么意思?
回复 支持 反对

使用道具 举报

发表于 2007-12-19 20:28:34 | 显示全部楼层
线程本来就共享同一进程的空间,何必多此一举呢
共享内存是为了传递大块的数据吧,如果只是消息,为什么不考虑别的ipc方式呢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-12-24 11:17:41 | 显示全部楼层
可能我的问题写的不太清晰,这么说吧:
假设有2个进程,1个开辟共享内存并且写入数据,shemget()函数的key为N;
第二个进程从该共享内存读取数据,为了找到正确的共享内存位置,它当然也要使用N作为key;
这2道进程是同一个程序员写的,有意而为之的。
现在另一个程序员写的第3个和第4个进程被启动,它们的工作方式和前2个一样,凑巧也是用N作为key来开辟和使用共享内存,这就完全在第一个程序员意料之外了。
这种情况下,2个生产者的互斥倒还好办,但第2个消费者完全可能访问第一个生产者生产的数据,因为它是靠key来分辨和它自己相关的生产者的,如何避免这个问题呢?

P.S. 我不是搞软件的,所以可能有些大家懒得说的简单编程规则都不懂,麻烦大虾说详细一点啊
回复 支持 反对

使用道具 举报

发表于 2007-12-24 12:45:21 | 显示全部楼层
首先,线程和进程是两个不同的概念。

回到这个问题,如果是父子进程间共享,那么可以用 IPC_PRIVATE 作为 key。

如果是两个进程间,那么用 ftok 来产生一个 key。选择产生 key 的文件路径的方法很多,比方说如果本来这段内存的内容就是从某个文件读入的,那么就用那个文件就好了。也可以用程序自己的路径。总之,用你这个软件私有的文件就好了。
回复 支持 反对

使用道具 举报

发表于 2007-12-25 08:54:47 | 显示全部楼层
就是为了避免这种冲突, 所以一般这个 key 都不是随便写一个数字就好了的, 而是通过 ftok() 函数来产生, 它接受一个路径名和一个标志作为参数, 不同的文件名会产生不同的 key, 通过使用 ftok() 函数可以尽量避免冲突, 但是并不能完全避免冲突, 只是一种努力而已.

尽管冲突不可完全避免, 但是问题在于应该由谁来避免冲突. 确实, 开源软件种类丰富, 数量众多, 那么大家如何减少冲突呢? 编程人员应该尽量保证自己去避免与别人的冲突, 而不是反过来. 回到共享内在的问题来说, 便是不要定死使用一个确定的 key, 而是约定一种生成 key 的规则. 比如就用 ftok() 来生成 key. 如果我们这里假定由生产者来开辟共享内存, 而且它要使用 "/tmp/.abc001" 作为生成 key 的路径名, 但是它检测到此文件已经存在, 那么就试着使用 /tmp/.abc002 好了. 然后消费者呢? 它对于 /tmp/.abcxxx 的形式来说应该是可配置的, 但是它可以有一个默认的值, 比如 /tmp/.abc001.

想一想, 很多现实中的程序都是这样的, 不是么, 毕竟最有可能和自己产生冲突的恰恰就是自己的另一个进程. 以 qvfb 为例, 它以 /tmp/.qtvfb_mouse-N 作为路径开辟一块共享内存, N 从 0 开始计算. 这个文件名同时会被创建成一个有名管道, 如果有多个 qvfb 进程就产生多个这样的管道, 而当 qvfb 的某个进程退出时它会删除这一管道文件. 另一方面, 客户端程序只要让它去连接一个管道未被占用的 qvfb 就可以了, 并打开这个管道, 以确保别人无法再打开它. 这就是通过协商的方式来解决冲突.

个人拙见, 仅供参考

P.S. 昨天似乎网络比较差, 回复了半天都不成功, 有人遇到同样的问题么?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-12-29 10:51:27 | 显示全部楼层
基本明白了,多谢各位。
尤其remote兄,说的很清楚
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表