#include
#include
#include
#include
#include
#include
#include
#include
#define SHM_SIZE 1024 //共享記憶體的大小
int main(int argc,char *argv[])
{
int ret, //臨時變量
pid, //程序id
sme_id, //儲存信号量描述符
shm_id; //儲存共享記憶體描述符
key_t sme_key, //儲存信号量鍵值
shm_key; //儲存共享記憶體鍵值
char *shmp; //指向共享記憶體的首位址
struct shmid_ds dsbuf; //定義共享記憶體資訊結構變量
struct sembuf lock = {0, -1, SEM_UNDO}; //信号量上鎖操作的數組指針
struct sembuf unlock = {0, 1, SEM_UNDO | IPC_NOWAIT};//信号量解鎖操作的數組指針
shm_key = ftok(*(argv+1), 2); //擷取信号量鍵值
if(shm_key
{
perror("ftok"); //調用ftok函數出錯
exit(0);
}
sme_id = semget(shm_key, 1, IPC_CREAT | 0666); //擷取信号量ID
if(sme_id
{
perror("semget"); //調用semget函數出錯
exit(0);
}
shm_key = ftok(*(argv+2), 1); //擷取共享記憶體鍵值
if(shm_key
{
perror("ftok");
exit(0);
}
shm_id = shmget(shm_key, SHM_SIZE, IPC_CREAT | 0666); //擷取共享記憶體ID
if(shm_id
{
perror("shmget");
exit(0);
}
shmp = shmat(shm_id, NULL, 0); //映像共享記憶體
if((int)shmp == -1)
{
perror("shmat");
exit(0);
}
pid = fork(); //建立子程序
if(pid
{
perror("fork");
exit(0);
}
else if(pid == 0) //子程序
{
ret = semctl(sme_id, 0, SETVAL, 1); //初始化信号量,初值設為1
if(ret == -1)
{
perror("semctl");
exit(0);
}
ret = semop(sme_id, &lock, 1); //申請通路共享資源,鎖定臨界資源
if(ret == -1)
{
perror("semop lock");
exit(0);
}
sleep(4); //讓子程序睡眠4秒
strcpy(shmp, "hello\n"); //往共享記憶體寫入資料
if(shmdt((void *)shmp)
{
perror("shmdt");
}
ret = semop(sme_id, &unlock, 1); //解鎖臨界資源
if(ret == -1)
{
perror("semop unlock");
exit(0);
}
}
else //父程序
{
sleep(1); //先讓子程序運作
ret = semop(sme_id, &lock, 1); //申請通路共享資源,鎖定臨界資源
if(ret == -1)
{
perror("semop lock");
exit(0);
}
if(shmctl(shm_id, IPC_STAT, &dsbuf)
{
perror("shmctl");
exit(0);
}
else
{
printf("Shared Memory Information:\n");
printf("\tCreator PID: %d\n", dsbuf.shm_cpid);
printf("\tSize(bytes): %d\n",dsbuf.shm_segsz);
printf("\tLast Operator PID: %d\n",dsbuf.shm_lpid);
printf("Received message : %s\n", (char *)shmp);
}
if(shmdt((void *)shmp)
{
perror("shmdt");
exit(0);
}
ret = semop(sme_id, &unlock, 1); //解鎖臨界資源
if(ret == -1)
{
perror("semop unlock");
exit(0);
}
if(shmctl(shm_id, IPC_RMID, NULL)
{
perror("shmctl");
exit(0);
}
ret = semctl(sme_id, 0, IPC_RMID, NULL); //删除信号量
if(ret == -1)
{
perror("semctl");
exit(0);
}
}
return 0;
}