信号量
信号量就是用来管理临界资源的,什么是临界资源呢?也就是一次性只能一个进程访问的资源,比如共享内存,信号不是通信,而是用来管理临界资源的。
semget | semctl | semop | |
---|---|---|---|
semget创建/打开信号量集
int semget(key_t key, int nsems, int semflg);
brief:用于创建或者打开一个信号量集
param:key,一个健值,如果另一个进程想访问这个信号量,就必须通过这个key来访问,nsems,创建一个信号量集(集就是一个数组,从0开始),semflg,创建信号量,或者打开,给予一定的权限。
return:返回-1创建失败
semctl删除/初始化信号量
int semctl(int semid, int semnum, int cmd, ...);
union semun { int val;//用于对信号量的状态,是否有资源,有1,无0 };
param:semid,即信号量返回的id,semnum,对哪个信号量进行删除或者初始化(因为信号量集,这里第一个信号量是从下标0开始,0也就是第一个信号量),cmd,即删除/初始化的命令,删除IPC_RMID,初始化命令SETVAL,还需要用到一个联合体
return:失败-1
semopPV操作
int semop(int semid, struct sembuf *sops, size_t nsops);
struct sembuf{ unsighed short sem_num;//信号量的编号,也就是第几个信号量 short sem_op;//P操作,= -1,V操作=1 short sem_flg;//是堵塞,还是非堵塞(如果没有获取到资源或放回资源就堵塞)SEM_UNDO };
brief:进行PV操作
param:semid,即semget返回的id,sops,一个结构体对PV操作的处理,nsops,操作信号量的个数
return:失败返回-1
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
//int semget(key_t key, int nsems, int semflg);
//int semctl(int semid, int semnum, int cmd, ...);
//int semop(int semid, struct sembuf *sops, size_t nsops);
/*
struct sembuf{
unsighed short sem_num;//信号量的编号,也就是第几个信号量
short sem_op;//P操作,= -1,V操作=1
short sem_flg;//是堵塞,还是非堵塞(如果没有获取到资源或放回资源就堵塞)SEM_UNDO
};*/
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) */
};
void PGetKey(int semid)
{
struct sembuf set;
set.sem_num = 0;
set.sem_op = -1;
set.sem_flg = SEM_UNDO;
semop(semid,&set,1);
}
void VPutKey(int semid)
{
struct sembuf set;
set.sem_num = 0;//信号量的编号
set.sem_op = 1;
set.sem_flg = SEM_UNDO;
semop(semid,&set,1);//信号量的个数
}
void main()
{
int semid;
pid_t pid;
key_t key;
int cnt;
key = ftok(".",9);
semid = semget(key,1,IPC_CREAT|0600);
if(semid < 0)
{
printf("creat semget error\n");
}
union semun initsem;
initsem.val = 0;//初始化信号量,让信号量的钥匙被拿走
semctl(semid,0,SETVAL,initsem);//初始化信号量SET_VAL
pid = fork();
while(1)
{ //printf("plase input 1-> ON 0-> OFF\n");
//scanf("%d",&cnt);
//if(cnt == 1)
//{
if(pid == 0)
{
PGetKey(semid);
printf("This is Son\n");
VPutKey(semid);
}
if(pid > 0)
{
printf("This is Father\n");
VPutKey(semid);
}
//}
/*if(cnt == 0)
{
break;
exit(0);
}*/
}
}
信号量管理共享内存
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
void PGetLock(int semid)
{
struct sembuf p;
p.sem_num = 0;
p.sem_op = -1;
p.sem_flg = SEM_UNDO ;
semop(semid,&p,1);
//printf("GET LOCK\n");
}
void VPutLock(int semid)
{
struct sembuf v;
v.sem_num = 0;
v.sem_op = 1;
v.sem_flg = SEM_UNDO;
semop(semid,&v,1);
//printf("PUT LOCK\n");
}
union semun
{
int val;
};
void main()
{
int semid;
int key;
int pid;
int shmid;
char *father;
char *son;
key = ftok(".",1);
shmid = shmget(key,1024,IPC_CREAT|0600);
semid = semget(key,1,IPC_CREAT|0666);
if(semid == -1)
{
printf("create semget lose!");
exit(-1);
}
union semun init;
init.val = 0;
semctl(semid,0,SETVAL,init);
pid = fork();
if(pid < 0)
{
printf("create pid error");
exit(-2);
}
if(pid > 0)
{
while(1)
{
PGetLock(semid);
son =(char *) shmat(shmid,0,0);
printf("father :%s\n",son);
printf("-------------------------\n");
father = (char *)shmat(shmid,0,0);
printf("father please input ptr:");
fgets(father,32,stdin);
VPutLock(semid);
}
}
if(pid == 0)
{
while(1)
{
son = (char *)shmat(shmid,0,0);
printf("son palse input ptr:");
fgets(son,32,stdin);
father = (char *)shmat(shmid,0,0);
printf("son :%s\n",father);
printf("-------------------------\n");
VPutLock(semid);
}
}
}
输出结果:单双共能实现,这个代码我写的全双工,前面运行过程有bug,但后面完全可以用