1.server.c
#include"utili.h"
int main(int argc, char const* argv[])
{
key_t shm_key = ftok(argv[1], 0xff);
if(shm_key == -1)
{
perror("ftok");
exit(EXIT_FAILURE);
}
int shm_id = shmget(shm_key, 1024, IPC_CREAT | 0755);
if(shm_id == -1)
{
perror("shmget");
exit(EXIT_FAILURE);
}
char *shm_addr = (char *)shmat(shm_id, NULL, 0);
if(shm_addr == (void *)-1)
{
perror("shmat");
shmctl(shm_id, IPC_RMID, NULL);
exit(EXIT_FAILURE);
}
/////////////////////////////////////////////////////////////////////////////
//它本身不提供同步访问机制,需要我们自己控制,所以加入信号量,使得可以进行同步
key_t sem_key = ftok("mysem", 0xff);
if(sem_key == -1)
{
perror("ftok sem");
exit(EXIT_FAILURE);
}
int sem_id = semget(sem_key, 2, IPC_CREAT | 0755);
if(sem_id == -1)
{
perror("semget");
exit(EXIT_FAILURE);
}
//初始化信号量集
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
union semun init_val;
init_val.val = 0;
semctl(sem_id, 0, SETVAL, init_val);
semctl(sem_id, 1, SETVAL, init_val);
//sem_num sem_op sem_flg
//0信号量成员类似读管道,却不存放数据,只负责阻塞和非阻塞
//1信号量成员类似写管道,却不存放数据,只负责阻塞和非阻塞
struct sembuf p = {1, -1, 0},
v = {0, 1, 0};
while(1)
{
printf("Ser:>");
scanf("%s", shm_addr);
if(strcmp(shm_addr, "quit") == 0)
{
shmdt(shm_addr);
break;
}
semop(sem_id, &v, 1);//server写入了内容,不阻塞
semop(sem_id, &p, 1);//client没有读取server内容之前,并且client读取之后,client没有产生对话一直阻塞
printf("Cli:>%s\n", shm_addr);
}
return 0;
}
2.client.c
#include"utili.h"
int main(int argc, char const* argv[])
{
key_t shm_key = ftok(argv[1], 0xff);
if(shm_key == -1)
{
perror("ftok");
exit(EXIT_FAILURE);
}
int shm_id = shmget(shm_key, 0, 0);
if(shm_id == -1)
{
perror("shmget");
exit(EXIT_FAILURE);
}
char *shm_addr = (char *)shmat(shm_id, NULL, 0);
if(shm_addr == (void*)-1)
{
perror("shmat");
exit(EXIT_FAILURE);
}
int sem_key = ftok("mysem", 0xff);
if(sem_key == -1)
{
perror("ftok sem");
exit(EXIT_FAILURE);
}
int sem_id = semget(sem_key, 0, 0);
if(sem_id == -1)
{
perror("semget");
exit(EXIT_FAILURE);
}
//1信号量成员类似读,0信号量成员类似写
struct sembuf p = {0, -1, 0},
v = {1, 1, 0};
while(1)
{
semop(sem_id, &p, 1);//server未写入,则一直阻塞
printf("Ser:>%s", shm_addr);//client读取server中的内容
printf("Cli:>");
scanf("%s", shm_addr);
if(strcmp(shm_addr, "quit") == 0)
{
shmdt(shm_addr);
break;
}
semop(sem_id, &v, 1);//client未写入内容前server一直阻塞,一旦写入,server非阻塞
}
return 0;
}
3.utili.h
#include<stdio.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdlib.h>
#include<string.h>
#include<sys/sem.h>
4.Makefile
ALL:server client
server:server.c
gcc server.c -o server
client:client.c
gcc client.c -o client
clean:
/bin/rm -f server client
测试