Shared Memory
Shared Memory is easily to understand, especially after grasping semaphore.
Normally, if we execute a piece of program twice (make them running at the same time), variables with the same name will occupy different physical memory. That means if in p1(one of the running process) the system makes x++, in p2(another running process) the same-name variable x will not be affected.
But sometimes we need that the 2 processes could influence each other for communication, then we can use shared memory.
Similar to semaphore, we use get function to obtain an ID.
int shmget(key_t key, size_t size, int shmflg);
shmget() returns an ID pointing to the shared memory associated to the parameter key. The 2nd argument size indicates the memory size that will be allocated, And we usually set shmflg to 0666 | IPC_CREAT.
After we execute the shmget() function, the memory could not be accessed yet. We should use shmat() to attach the shared memory to the calling process, so that the process could perform operations on the memory.
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmid is the ID returned by shmget(). If we set shmaddr to (void *)0, the system will find a suitable memory to allocate. And usually we set shmflg to 0.
The opposite one to shmat() is shmdt() -- to detach the shared memory from the calling process so that the process could not operate with it any more unless shmat() again.
The prototype of shmdt() is :
int shmdt(const void *shmaddr);
Finally, we use shmctl() to remove the shared memory.
Usually we use shmctl(shmid, IPC_RMID, 0).
以下是一个小实验,我们用shm1.c来对共享内存写消息,然后用shm2.c来读取。
shm1.c:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/shm.h> int main(){ int shm_id; char *addr; char buf[100]; printf("請輸入要发送的消息:"); scanf("%s", buf); shm_id = shmget((key_t)1234, sizeof(buf), 0666 | IPC_CREAT); addr = (char *)shmat(shm_id, (void *)0, 0); strcpy(addr, buf); shmdt((void *)addr); return 0; }
shm2.c:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/shm.h> int main(){ int shm_id; char *addr; char buf[100]; shm_id = shmget((key_t)1234, sizeof(buf), 0666 | IPC_CREAT); addr = (char *)shmat(shm_id, (void *)0, 0); printf("获取到共享内存中数据: %s/n", addr); shmdt((void *)addr); shmctl(shm_id, IPC_RMID, 0); return 0; }
对两段代码编譯执行:
$ ./shm1 請輸入要发送的消息:hello,shm2 $ ./shm2 获取到共享内存中数据: hello,shm2
需要注意的是对共享内存的读写并不是原子操作,可能出现读到一半的时候另一个进程重写了共享内存,这样难免会出现错误。 关于这一点,则需要编程人员来控制。
Jason Lee
2009-11-15 p.m