共享內存小記
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
最後更新:2017-04-02 04:01:43