/* ************************************************************************
* Filename: sharewrite_sem.c
* Description:
* Version: 1.0
* Created: 05/09/2020 02:45:05 AM
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (WCT),
* Company:
* ************************************************************************/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int sem_id = 0;
union semun{
int val;
struct semid_ds *bug;
unsigned short *arry;
};
typedef struct{
char name[4];
int age;
} people;
/*****************************
* 信号量操作 *
******************************/
// 初始化设置信号令的值
static int set_semvalue(){
union semun sem_union;
sem_union.val = 0;
if ( semctl( sem_id, 0, SETVAL, sem_union) == -1 ){
return 0;
}
return 1;
}
// 删除不再使用信号量
static void del_semvalue(){
union semun sem_union;
if ( semctl ( sem_id, 0, IPC_RMID, sem_union) == -1 ){
fprintf(stderr, "Failed to delete semaphore\n");
}
}
// 获取某信号量的值
static int get_semvalue(){
union semun sem_union;
int t = semctl( sem_id, 0, GETVAL, sem_union);
if( t == -1 ){
// 错误处理
}
return t;
}
// 对信号量进行 P 操作
static int semaphore_p(){
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1; // P()
sem_b.sem_flg = SEM_UNDO;
if ( semop( sem_id, &sem_b, 1 ) == -1 ){
fprintf( stderr, "semaphore_p failed\n");
return 0;
}
return 1;
}
// 对信号量进行 V 操作
static int semaphore_v(){
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; // V()
sem_b.sem_flg = SEM_UNDO;
if ( semop( sem_id, &sem_b, 1 ) == -1 ){
fprintf( stderr, "semaphore_v failed\n");
return 0;
}
return 1;
}
/**************************************************************************/
int main(int argc, char** argv)
{
int shm_id, i;
key_t key;
char temp;
people *p_map;
char* name = "/home/wct/IPC";
key = ftok(name,0); // 将文件或目录路径转换为键值
if(key==-1){
perror("ftok error");
}
// 如果内核中存在了 key ,就返回共享内存的标识符,反之则创建
shm_id=shmget(key,4096,IPC_CREAT);
// 创建信号量, 内核中存在 key 值,则返回已有信号量的标识, 反之,创建信号量
sem_id = semget( (key_t)1234, 1, 0666 | IPC_CREAT);
set_semvalue();
//printf( "semnum = %d\n", get_semvalue());
if( shm_id == -1 || sem_id == -1 ){
perror("shmget/semget error");
return -1;
}
p_map=(people*)shmat(shm_id,NULL,0);// 将共享内存映射到该程序的进程空间,以读写的方式共享内存
temp='a' - 1;
for(i = 0;i<10;i++)
{
temp+=1;
memcpy((*(p_map+i)).name,&temp,1);
(*(p_map+i)).age=20+i;
printf("Write: name: %s\tage: %d\n", ( * ( p_map + i)).name, ( *( p_map + i )).age);
// 对信号量执行 V 操作
if( ! semaphore_v() ){
exit( EXIT_FAILURE );
}
// printf( "semnum = %d\n", get_semvalue());
sleep(rand() % 3);
}
if(shmdt(p_map)==-1){
perror(" detach error ");
}
while( get_semvalue() > 0 ); // 等待数据被读取完
return 0;
}