#ifndef __SEM_H__ #define __SEM_H__ #include02sem信号灯.c#include #include #include #include // 1、获取key值-创建信号量 ->2、初始化 int sem_init(void); //3、信号灯的操作(PV)semop //3、1 P操作代表申请资源 int P(int semid, int semnum); //3、2 V操作代表释放资源 int V(int semid, int semnum); //4、删除信号灯semctl int sem_del(int semid); #endif
#include03write.c#include #include #include #include //2、1定义联合体 union semun { int val; //!!!!!!! struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; }; //2、初始化信号量semctl int init_semnum_value(int semid, int semnum, int value) { union semun sem;//定义联合体 要写定义 sem.val = value;//设置信号灯的值 !!!!!!!!!!!!!!! //信号灯的编号,SETVAL[设置信号灯的值] if (semctl(semid, semnum, SETVAL, sem) < 0) printf("semctl init value error"); return 0; } // 1、获取key值-创建信号量 ->2、初始化 int sem_init(void) { // 1.获取key值 key_t key; //改你有的目录 if ((key = ftok("/home/linux", 'w')) == -1) printf("ftok error"); // 2.创建信号量semget //如果信号量不存在就创建信号量,创建号信号量后执行else语句对 //信号灯的初值进行初始化 //如果信号量已存在,IPC_EXCL这个就会让semget报EEXIST,如果 //信号灯已存在,直接获取信号灯semid,否则打印错误。如果信号 //量已存在就不再对信号量中的信号灯的初值做初始化了 int semid; //创建|存在 if ((semid = semget(key, 2, IPC_CREAT | IPC_EXCL | 0664)) == -1) { if (errno == EEXIST)//存在-返回错误码EEXIST { semid = semget(key, 2, IPC_CREAT | 0664);//semget成功返回ID } else { printf("create sem error"); } } else { // 3.初始化信号量semctl //初始化信号灯集中的两个信号灯的初值 // 0号灯的初值为0 // 1号灯的初值为1 init_semnum_value(semid, 0, 0); init_semnum_value(semid, 1, 1); } return semid; } //3、信号灯的操作(PV)semop //3、1 P操作代表申请资源 int P(int semid, int semnum) { struct sembuf buf;//操作方式结构体 不用写结构体定义 buf.sem_num = semnum;//信号灯的编号 buf.sem_op = -1; //申请资源 buf.sem_flg = 0; //阻塞方式申请 //操作方式结构体首地址,1操作信号灯的个数 if (semop(semid, &buf, 1) < 0) printf("P error"); return 0; //成功返回0 } //3、2 V操作代表释放资源 int V(int semid, int semnum) { struct sembuf buf;//操作方式结构体 不用写结构体定义 buf.sem_num = semnum;//信号灯的编号 buf.sem_op = 1; //释放资源 buf.sem_flg = 0; //阻塞方式申请 //操作方式结构体首地址,1操作信号灯的个数 if (semop(semid, &buf, 1) < 0) printf("V error"); return 0; //成功返回0 } //4、删除信号灯semctl int sem_del(int semid) { // 1.删除信号灯集合--IPC_RMID[删除信号灯集] if (semctl(semid, 0, IPC_RMID, NULL) == -1) printf("delete sem error"); }
#include "./01sem.h"
//申请共享内存的大小
#define shmSIZE 4096
int main(int argc, char const *argv[])
{
// 1、创建信号量---信号灯集
int semid; //信号灯集的ID
if ((semid = sem_init()) == -1)
printf("sem_init error");
printf("semid = %dn", semid);
// 1.获取key----共享内存
key_t key;
//改你有的目录
if ((key = ftok("/home/linux", 't')) == -1)
printf("ftok eroorn");
// 2.创建共享内存----共享内存
int shmid;
if ((shmid = shmget(key, shmSIZE, IPC_CREAT | 0664)) == -1)
printf("shmget eroorn");
printf("shmid = %dn", shmid);
// 3.映射内存----共享内存
//映射后的地址
// char *addr=NULL;
char *addr;
if ((addr = shmat(shmid, NULL, 0)) == (void *)-1)
printf("shmat eroorn");
// 4.写入信息----共享内存
while (1)
{
//2、信号灯的操作
//2、1 P操作代表申请资源
P(semid,1);
printf("老王> ");
//从终端获取信息
fgets(addr, shmSIZE, stdin);
//处理输入最后一个换行符
addr[strlen(addr) - 1] = ' ';
//2、2 V操作代表释放资源
V(semid,0);//----->read要申请0号灯
if (strcmp(addr,"quit")==0)
break;
// 2、3 P操作代表申请资源
P(semid, 0);
printf("n");
system("date") ;
printf("小姐姐> %sn", addr);
printf("n");
// 2、4 V操作代表释放资源
V(semid, 1);
if (strcmp(addr, "quit") == 0)
break;
}
//删除共享内存
shmctl(shmid, IPC_RMID, NULL);
//3、删除信号灯集
sem_del(semid);
return 0;
}
04read.c
#include "./01sem.h"
//申请共享内存的大小
#define shmSIZE 4096
int main(int argc, char const *argv[])
{
// 1、创建信号量---信号灯集
int semid; //信号灯集的ID
if ((semid = sem_init()) == -1)
printf("sem_init error");
printf("semid = %dn", semid);
// 1.获取key----共享内存
key_t key;
//改你有的目录
if ((key = ftok("/home/linux", 't')) == -1)
printf("ftok eroorn");
// 2.创建共享内存----共享内存
int shmid;
if ((shmid = shmget(key, shmSIZE, IPC_CREAT | 0664)) == -1)
printf("shmget eroorn");
printf("shmid = %dn", shmid);
// 3.映射内存----共享内存
//映射后的地址
// char *addr=NULL;
char *addr;
if ((addr = shmat(shmid, NULL, 0)) == (void *)-1)
printf("shmat eroorn");
// 4.读取信息----共享内存
//从终端获取信息
while (1)
{
// 2、信号灯的操作
// 2、1 P操作代表申请资源
P(semid, 0);
printf("n");
system("date") ;
printf("老王> %sn", addr);
printf("n");
// 2、2 V操作代表释放资源
V(semid, 1);
if (strcmp(addr, "quit") == 0)
break;
//2、3 P操作代表申请资源
P(semid, 1);
printf("小姐姐> ");
//从终端获取信息
fgets(addr, shmSIZE, stdin);
//处理输入最后一个换行符
addr[strlen(addr) - 1] = ' ';
//2、4 V操作代表释放资源
V(semid,0);
if (strcmp(addr,"quit")==0)
break;
}
return 0;
}
执行命令
1.gcc 03write.c 02sem信号灯.c -o write
2…/write
3.gcc 02sem信号灯.c 04read.c -o read
4…/read
执行如下命令->删除原有的 semid



