Linux給我們提供了豐富的內部進程通信機制,包括共享內存、內存映射文件、先入先出(FIFO)、接口(sockets)以及多種用於同步的標識。在本文中,我們主要討論一下共享內存和內存映射文件技術。
一般來說,內部進程通信(interprocess communication)也就是IPC,是指兩個或兩個以上進程以及兩個或者兩個以上線程之間進行通信聯系。每個IPC機制都有不同的強項或者弱點,不過沒有一個IPC機制包含內建的同步方法。因此程序員不但需要自己在程序中實現同步,而且還需要為了利用IPC機制而自己開發通信協議。
共享內存
使用共享內存和使用malloc來分配內存區域很相似。使用共享內存的方法是:
1.對一個進程/線程使用shmget分配內存區域。
2.使用shmat放置一個或多個進程/線程在共享內存中,你也可以用shmctl來獲取信息或者控制共享區域。
3.使用shmdt從共享區域中分離。
4.使用shmctl解除分配空間
下面是個例子:
//建立共享內存區域 intshared_id; char *region; const intshm_size = 1024; shared_id = shmget(IPC_PRIVATE,//保證使用唯一ID shm_size, IPC_CREAT IPC_EXCL //創建一個新的內存區域 S_IRUSR S_IWUSR);//使當前用戶可以讀寫這個區域 //交叉進程或生成進程. //將新建的內存區域放入進程/線程 region = (char*) shmat(segment_id, 0, 0); //其他程序代碼 ... //將各個進程/線程分離出來 shmdt(region); //破壞掉共享內存區域 shmctl(shared_id, IPC_RMID, 0);
共享內存是Linux中最快速的IPC方法。他也是一個雙向過程,共享區域內的任何進程都可以讀寫內存。這個機制的不利方面是其同步和協議都不受程序員控制,你必須確保將句柄傳遞給了子進程和線程。
內存映射文件
內存映射文件不僅僅用於IPC,在其他進程中它也有很大作用。如果你需要將一個分配的緩沖區初始化為零,只要記住/dev/zero 。你也可以通過將文件映射到內存中以提高其性能。它使你可以像讀寫字符串一樣讀寫文件。下面是個例子:
const char filename[] = "testfile"; intfd; char *mapped_mem; const intflength = 1024; fd = open(filename, O_RDWR O_CREAT, S_IRUSR S_IWUSR); lseek(fd, flength + 1, SEEK_SET); write(fd, "\0", 1); lseek(fd, 0, SEEK_SET); mapped_mem = mmap(0, flength, PROT_WRITE, //允許寫入 MAP_SHARED,//寫入內容被立即寫入到文件 fd, 0); close(fd); //使用映射區域. ... munmap(file_memory, flength);
利用內存映射來處理IPC的好處是在整個過程中你不需要處理句柄:只要打開文件並把它映射在合適的位置就行了。你可以在兩個不相關的進程間使用內存映射文件。
使用內存映射的缺點是速度不如共享內存快。如果湊巧文件很大,所需要的虛擬內存就會很大,這樣會造成整體性能下降。
更多內容請看Linux集群高級技巧 共享上網專題專題,或