- 信号灯集(信号量数组):
- 1、实现
进程同步的机制
;
- 2、在一个信号灯集中,可以有很多信号灯;
- 3、这些信号灯集中的信号灯
相互独立
,每个灯的值的改变都不会影响到其他的信号灯;
- 4、信号灯的值一般设置为
二值量
,即0或者1
,其中0代表没有资源
,1代表有资源
;
- 常用的接口函数:
- 一、创建一个信号灯集(semget函数):
#include
int semget(key_t key, int nsems, int semflg);
#include
int semctl(int semid, int semnum, int cmd, ...);
union semun{
int val;
struct semid_ds *buf;
};
#include
int semop(int semid, struct sembuf *sops, size_t nsops);
#ifndef __SEM_H__
#define __SEM_H__
int sem_init(int nsems);
int sem_wait_P(int semid,int sem_num);
int sem_post_V(int semid,int sem_num);
int sem_exit(int semid);
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include "sem.h"
#include
union semun {
int val;
struct semid_ds *buf;
};
int sem_init(int nsems)
{
int semid = 0;
key_t key = ftok("/home/linux/work", 'K');
if(-1 == key)
{
perror("ftok error");
exit(-1);
}
if(-1 == (semid = semget(key,nsems,IPC_CREAT|IPC_EXCL|0666)))
{
if(EEXIST == errno)
{
if(-1 == (semid = semget(key,nsems,IPC_CREAT|0666)))
{
perror("semget error");
exit(-1);
}
return semid;
}
else
{
perror("semget error");
exit(-1);
}
}
union semun myval = {.val = 1};
if(-1 == semctl(semid,0,SETVAL,myval))
{
perror("semctl error");
exit(-1);
}
myval.val = 0;
for(int i = 1; i < nsems; i++)
{
if(-1 == semctl(semid,i,SETVAL,myval))
{
perror("semctl error");
exit(-1);
}
}
return semid;
}
int sem_wait_P(int semid,int sem_num)
{
struct sembuf mysem;
mysem.sem_num = sem_num;
mysem.sem_op = -1;
mysem.sem_flg = 0;
if(-1 == semop(semid,&mysem,1))
{
perror("semop error");
exit(-1);
}
}
int sem_post_V(int semid,int sem_num)
{
struct sembuf mysem;
mysem.sem_num = sem_num;
mysem.sem_op = 1;
mysem.sem_flg = 0;
if(-1 == semop(semid,&mysem,1))
{
perror("semop error");
exit(-1);
}
}
int sem_exit(int semid)
{
if(-1 == semctl(semid,0,IPC_RMID))
{
perror("semctl error");
exit(-1);
}
}
#include
#include
#include
#include
#include
#include
#include
#include
#include "sem.h"
#include
#define PIGE_SIZE 4*1024
int main(int argc, char const *argv[])
{
key_t key = ftok("/home/linux/work", 'K');
if(-1 == key)
{
perror("ftok error");
exit(-1);
}
int shmid = shmget(key,2*PIGE_SIZE,IPC_CREAT|0666);
if(-1 == shmid)
{
perror("shmget error");
exit(-1);
}
char *k_addr = shmat(shmid,NULL,0);
if((void *)-1 == k_addr)
{
perror("shmat error");
exit(-1);
}
int semid = sem_init(2);
while(1)
{
sem_wait_P(semid,0);
fgets(k_addr,128,stdin);
k_addr[strlen(k_addr)-1] = '\0';
sem_post_V(semid,1);
if(!strncmp(k_addr,"exit",4))
{
break;
}
}
if(-1 == shmdt(k_addr))
{
perror("shmdt error");
exit(-1);
}
if(-1 == shmctl(shmid,IPC_RMID,NULL))
{
perror("shmctl error");
exit(-1);
}
sem_exit(semid);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include "sem.h"
#include
#define PIGE_SIZE 4*1024
int main(int argc, char const *argv[])
{
key_t key = ftok("/home/linux/work", 'K');
if(-1 == key)
{
perror("ftok error");
exit(-1);
}
int shmid = shmget(key,2*PIGE_SIZE,IPC_CREAT|0666);
if(-1 == shmid)
{
perror("shmget error");
exit(-1);
}
char *k_addr = shmat(shmid,NULL,0);
if((void *)-1 == k_addr)
{
perror("shmat error");
exit(-1);
}
int semid = sem_init(2);
while(1)
{
sem_wait_P(semid,1);
printf("[%s]\n",k_addr);
if(!strcmp(k_addr,"exit"))
{
break;
}
sem_post_V(semid,0);
}
if(-1 == shmdt(k_addr))
{
perror("shmdt error");
exit(-1);
}
if(-1 == shmctl(shmid,IPC_RMID,NULL))
{
perror("shmctl error");
exit(-1);
}
sem_exit(semid);
return 0;
}
linux@ubuntu:~/work/MSG/SME$ ./w
hello
hi
I Love China
linux@ubuntu:~/work/MSG/SME$ ./r
[hello]
[hi]
[I Love China]