還是以操作系統(tǒng)第三章大作業(yè)中的一項作為導(dǎo)入。

大作業(yè)2要求.png
共享內(nèi)存就是允許多個不相關(guān)的進程共享訪問的一個邏輯內(nèi)存,是進程間數(shù)據(jù)共享的一種很有效的方式。所有進程都可以對這片區(qū)域進行寫入、讀取,類似于全局變量吧。
使用共享內(nèi)存需要一些函數(shù)接口來實現(xiàn),如shmget函數(shù)創(chuàng)建共享內(nèi)存,shmat函數(shù)將共享內(nèi)存連接到進程,shmdt函數(shù)將共享內(nèi)存從進程中分離,shmctl函數(shù)可用來刪除共享內(nèi)存段。
有關(guān)函數(shù)的具體用法可參考Linux進程間通信——使用共享內(nèi)存
共享內(nèi)存并沒有提供同步機制,故我們需要使用信號量等方式來控制進程間的互斥。本例沒有使用信號量,而是使用了written作為標(biāo)志起到互斥量相同的作用。
下面直接丟代碼了,這個問題理解起來沒什么難度,就是熟悉對共享內(nèi)存的操作。模型也借用了上面博客的例子,進行了部分修改。詳細內(nèi)容見代碼及注釋。
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <assert.h>
#define TEXT_SIZE 1024
void shmread();
void shmwrite();
struct shared_struct
{
int written;//0表示可寫,非0表示可讀,類似于讀寫鎖
char text[TEXT_SIZE];//記錄讀寫的文本
};
void shmread()
{
int running = 1;//程序運行的標(biāo)志,1為運行
void *shm = NULL;//共享內(nèi)存的原始首地址
struct shared_struct *shared;//指向shm
int shmid;//共享內(nèi)存標(biāo)識符
key_t key;//key值
//創(chuàng)建key值
key = ftok("../", 1234);
assert(key!=-1);
//創(chuàng)建共享內(nèi)存
shmid = shmget(key, sizeof(struct shared_struct), 0666|IPC_CREAT);
assert(shmid!=-1); //值為假,則打印出錯信息并退出
//將共享內(nèi)存連接到當(dāng)前進程的地址空間
shm = shmat(shmid, 0, 0);
assert(shm!=(void*)-1);
//printf("\nMemory attached at %X\n", (int)shm);
//設(shè)置共享內(nèi)存
shared = (struct shared_struct*)shm;
shared->written = 0;
while(running)//讀取共享內(nèi)存的數(shù)據(jù)
{
//
if(shared->written != 0)
{
printf("You just wrote: %s", shared->text);
sleep(1);
//讀完數(shù)據(jù)后設(shè)置written使共享內(nèi)存段可寫
shared->written = 0;
//輸入end退出程序
if(strncmp(shared->text, "end", 3) == 0)
running = 0;
}
else//有其他進程在寫數(shù)據(jù)則不能讀取數(shù)據(jù)
sleep(1);
}
//將共享內(nèi)存從當(dāng)前進程分離
assert(shmdt(shm)!=-1);
//刪除共享內(nèi)存
assert(shmctl(shmid, IPC_RMID, 0) != -1);
exit(EXIT_SUCCESS);
}
void shmwrite()
{
int running = 1;
void *shm = NULL;
struct shared_struct *shared;
int shmid;
key_t key;
key = ftok("../", 1234);
assert(key!=-1);
char buffer[BUFSIZ + 1];//緩沖區(qū)用于保存輸入的文本,BUFSIZE=8192在stdlib.h中定義的
//創(chuàng)建
shmid = shmget(key, sizeof(struct shared_struct), 0666|IPC_CREAT);
assert(shmid!=-1);
//連接
shm = shmat(shmid, (void*)0, 0);
assert(shm!=(void*)-1);
//printf("Memory attached at %X\n", (int)shm);
//設(shè)置
shared = (struct shared_struct*)shm;
while(running)//寫數(shù)據(jù)
{
//等待數(shù)據(jù)被讀取后再寫數(shù)據(jù)
while(shared->written == 1)
{
sleep(1);
printf("Waiting...\n");
}
//寫數(shù)據(jù)
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
strncpy(shared->text, buffer, TEXT_SIZE);
//寫數(shù)據(jù)后設(shè)置written使共享內(nèi)存段可讀
shared->written = 1;
//輸入end退出程序
if(strncmp(buffer, "end", 3) == 0)
running = 0;
}
//分離
assert(shmdt(shm)!=-1);
//sleep(2);
exit(EXIT_SUCCESS);
}
int main()
{
pid_t pid;
pid=fork();
if(pid==0) shmwrite(); //子進程使用共享區(qū)并讀數(shù)據(jù)
else shmread(); //父進程創(chuàng)建并使用共享區(qū)并寫數(shù)據(jù)
exit(0);
}
運行示例如圖。

運行示例.png
其他參考鏈接也列出
linux 共享內(nèi)存(實現(xiàn)進程之間通信)
共享內(nèi)存的實現(xiàn)詳解