免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1272 | 回复: 2
打印 上一主题 下一主题

共享内存的详细介绍。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-06-19 16:51 |只看该作者 |倒序浏览
《转载》

Overview of Shared Memory

Shared memory is pretty much exactly what it sounds like: memory that can be accessed by several processes. They are quite useful, but there is, of course, a catch: the commands provide ways for multiple processes to access the memory, but they don't control that access. Those of you who haven't slept through all of Tekin's lectures know that having unrestricted access to shared data is a bad thing. Luckily, you just learned about semaphores, so all you have to do is apply the theory that you have been learning in lecture.

One important thing to note is that although the commands for shared memory look a lot like those for semaphores, they work very differently in many important respects, so be sure you understand the differences.
Getting Shared Memory

In order to allocate shared memory, you'll use the shmget command, which looks like this:

shmget(key_t key, int size, int shmflg);

Which is, as I said, looks similar to semget. The return value is still the identifier, and the shmflg has all the same arguments (IPC_CREAT, IPC_EXCL, permissions (see the semaphore recitation notes for an explanation)) as for semget

The thing that's different is the second parameter, which is used to specify the size of the shared memory segment. Like malloc, you need to make sure you specify the amount of space (in bytes) that you will be using. This is one of those places where C is uglier than C++; C++ takes care of these details for you when you use the new command, but in C it's your problem. Fortunately, you needn't know what the size of each data type is (which is very good since it's platform dependant), thanks to the sizeof operator, which takes a parenthesized data-type or a variable name and returns it's space in bytes. So sizeof(char) returns 1, sizeof(struct mystruct) returns the number of bytes your struct occupies, and sizeof a returns the number of bytes for whatever type a is. So a typical call to semget to create a shared array of ten characters would be:

key_t mykey;
int shmid;
mykey=ftok(".", 'n');
shmid=shmget(mykey, 10*(sizeof(char)), IPC_CREAT | IPC_EXCL | 0666);
//error-check shmid against -1

Once again, the key parameter to ftok can be IPC_PRIVATE, if you want to make a shared memory block that no other process can access, so you don't care what the key is. Also, you only want to use the IPC_CREAT and IPC_EXCL flags for the process making the shared memory. All your other processes which use that memory should leave those flags out or the call will fail.

In the above example, all I wanted were characters, but if you wanted several different data types, there's no reason you can't get them all in one block, by using, say, sizeof(char)+6*(sizeof(int)) as the second parameter to shmget. The only drawback will be the added difficulty of finding the address of each piece of the block later (I'll explain in the next section).

A quick aside: the error checking done in many of the Monkey Book's example programs in Chapter 8 is quite good, so if you are still having trouble doing error checking, follow their examples.
Attaching Shared Memory

Unlike semaphores, just creating the shared memory isn't enough; you also have to attach it to your program. You do this with the appropriately named shmat command:

shmat(int shmid, void *shmaddr, int shmflg);

The first argument is self explanatory by now. The next one is used to try to control where in memory the shared segment is placed; you will never care for the purposes of this class, so just pass it a 0 (if you are curious what exactly it does, see pg 200). The last one lets you set any flags. The only one you might want is SHM_RDONLY, to make it read-only for that process. Usually though, you'll want the default permission of read/write, so that can be 0 as well.

shmat will return a void*; i.e. a non-typed pointer to the beginning of the memory segment. If you want to the shared memory for a single variable, just cast it to the appropriate pointer type. So assuming I had used shmget already to get memory with id shmid:

int *a;
a = (int *)shmat(shmid, 0, 0);

would let you use a just like a normal integer pointer. Similarly, if you want an array, the same sort of casting will work. All array indexes do is add the appropriate amount to a base pointer and dereference, so if in the example above the shared memory segment had been created with space for five integers (5*sizeof(int)), then an assignment such as a[2]=3; would be perfectly valid.

Things get uglier if you want to mix types. Consider the following code to get an array of 3 characters and an integer:

key_t mykey;
int shmid;
int *x;
char *cs;
void *base;

mykey=ftok(".", 'm');
shmid=shmget(mykey, 3*(sizeof(char))+sizeof(int), IPC_CREAT | IPC_EXCL | 0666);
//error checking should be done here
base = shmat(int shmid, 0, 0);
//error checking should be done here too
x = (int *)base;
a = (char *)(base+sizeof(int));

This will work fine, but it gets progressively uglier if you are doing several variables all in one block. I find it easier to just make another shared memory for different types. Remember that there is a system limit on shared memories though, so sometimes it's better to use only one instead of clogging up the machine with a lot of small separate segments.
Using Shared Memory

This is the easy part. Once you've done all that, you can pretend it's a regular variable (except that you need to control access to it). So you can use *x=8; and a[1]='b'; and anything else you are used to doing with pointers.
Cleaning Up

Again, cleaning up your shared memory, as with semaphores, is VERY IMPORTANT. There's an extra step with shared memory, and that is detaching it. Detach is done using, you guessed it, shmdt(void *shmaddr); where shmaddr is just the pointer you assigned shmat to (recast as a void*).

Then you need to actually delete the shared memory, which is done using the shmctl call, just like semctl for semaphores. You can also use shmctl for other things (see pg 19 but unlike semaphores there's no need to initialize shared memory with shmctl; just initialize it as you would a normal variable. The delete call for the above shared memory is:

shmctl(shmid, IPC_RMID, (struct shmid_ds *)0);

The last parameter is ignored for removing, just as it was it semctl, but you should still cast the null pointer appropriately.

Important note: Although every process needs to shmdt, only one removes the shared memory. The standard way of doing it is, whichever process actually created the memory (using the IPC_CREAT flag for shmget) is responsible for deleting it. Obviously in some applications that won't be the best method, but it's a good rule of thumb.nd anything else you are used to doing with pointers.
memcpy and Shared Memory with Files

A useful function worth mentioning is memcpy. While it's not restricted to shared memory, this is the first real use for it we've seen. The call is memcpy(void *s1, void *s2, size_t n) What it does it take the contents of the memory starting at s2 and copy n bytes to s1. It does not allocate memory for you, and it does not check that there is enough space in s1. So as usual in C, be sure that you have allocated space before calling the function[/quote]

论坛徽章:
0
2 [报告]
发表于 2003-06-19 23:14 |只看该作者

共享内存的详细介绍。

好像是unix环境网络编程上的

ftok时要注意不同平台上的不同限制

有的目录使用.
有的使用/

论坛徽章:
0
3 [报告]
发表于 2003-06-19 23:15 |只看该作者

共享内存的详细介绍。

具体还是看unp中解释

我觉得里面说得够好的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP