IPC-共享內存
父子進程之間
#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
#define SHM_SIZE 1024
int main(void)
{
int shmid = shmget(IPC_PRIVATE, SHM_SIZE, 0666|IPC_CREAT);
if(shmid == -1)
{
perror("shmget");
exit(EXIT_FAILURE);
}
if(fork() > 0)
{
char *pshm = shmat(shmid, NULL, 0); // 0表示可讀可寫
if(pshm == (char*)-1)
{
perror("shmat");
exit(EXIT_FAILURE);
}
memset(pshm, 0, SHM_SIZE);
strncpy(pshm, "Hello world", 11);
if(-1 == shmdt(pshm))
{
perror("shmdt");
exit(EXIT_FAILURE);
}
wait(NULL);
printf("parent finish\n");
return 0;
}
sleep(1);
char *pshm = shmat(shmid, NULL, 0);
if(pshm == (char*)-1)
{
perror("shmat");
exit(EXIT_FAILURE);
}
printf("child read from shm: %s\n", pshm);
return 0;
}
非親緣進程之間
問題描述:非親緣進程之間,a進程給b進程通過共享內存發送數據
shmwr.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#define FTOKPATHNAME "./shmwr.c"
struct MSG
{
int flag;
char data[1024];
};
int main(void)
{
key_t key = ftok(FTOKPATHNAME, 'a'); //ftok獲取一個唯一key,用於shmget
if(-1 == key)
{
perror("ftok");
exit(EXIT_FAILURE);
}
int shmid = shmget(key, sizeof(struct MSG), 0666|IPC_CREAT);
if(-1 == shmid)
{
perror("shmget");
exit(EXIT_FAILURE);
}
struct MSG *pmsg = (struct MSG *)shmat(shmid, NULL, 0); // 0表示可讀可寫
if((char*)pmsg == (char*)-1)
{
perror("shmat");
exit(EXIT_FAILURE);
}
memset(pmsg, 0, sizeof(struct MSG));
while(1)
{
if(pmsg->flag == 0)
{
int ret = read(STDIN_FILENO, pmsg->data, sizeof(pmsg->data));
if(-1 == ret)
{
perror("read");
exit(EXIT_FAILURE);
}
pmsg->flag = 1; //不能放在strncmp下面
putchar(10);
if(strncmp(pmsg->data, "over", 4) == 0)
break;
}
sleep(1);
}
if(-1 == shmdt(pmsg))
{
perror("shmdt");
exit(EXIT_FAILURE);
}
return 0;
}
shmrd.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#define FTOKPATHNAME "./shmwr.c"
struct MSG
{
int flag;
char data[1024];
};
int main(void)
{
key_t key = ftok(FTOKPATHNAME, 'a');
if(-1 == key)
{
perror("ftok");
exit(EXIT_FAILURE);
}
int shmid = shmget(key, sizeof(struct MSG), 0666|IPC_CREAT);
if(-1 == shmid)
{
perror("shmget");
exit(EXIT_FAILURE);
}
struct MSG *pmsg = (struct MSG *)shmat(shmid, NULL, 0);
if((char*)pmsg == (char*)-1)
{
perror("shmat");
exit(EXIT_FAILURE);
}
while(1)
{
if(pmsg->flag == 1)
{
if(strncmp(pmsg->data, "over", 4) == 0)
break;
write(STDOUT_FILENO, pmsg->data, strlen(pmsg->data));
putchar(10);
pmsg->flag = 0;
}
sleep(1);
}
if(-1 == shmdt(pmsg))
{
perror("shmdt");
exit(EXIT_FAILURE);
}
// 最後一個進程離開shmid所標識的共享內存時,把共享內存刪掉。
// 如果這不是最後一個進程離開,就把該共享內存標記爲刪除,真正的刪除在最後一個進程離開之後
if(-1 == shmctl(shmid, IPC_RMID, NULL)) // 當使用標籤IPC_RMID時,第三個參數應爲NULL
{
perror("shmctl");
exit(EXIT_FAILURE);
}
return 0;
}
使用共享內存的優缺點
優點:我們可以看到使用共享內存進行進程間的通信真的是非常方便,而且函數的接口也簡單,數據的共享還使進程間的數據不用傳送,而是直接訪問內存,也加快了程序的效率。同時,它也不像匿名管道那樣要求通信的進程有一定的父子關係。
缺點:共享內存沒有提供同步的機制,這使得我們在使用共享內存進行進程間通信時,往往要藉助其他的手段來進行進程間的同步工作。