本文共 3762 字,大约阅读时间需要 12 分钟。
信号灯集函数定义如下:
#include
int semctl(int sem_id, int sem_num, int command, ...);
int semget(key_t key, int num_sems, int sem_flags);
int semop(int semid, struct sembuf *sops, unsigned nsops);
semget函数创建一个新的信号量或是获得一个已存在的信号量键值。
semop函数用来改变信号量的值(包含P操作和V操作)。
semctl函数允许信号量信息的直接控制(包含初始化信号灯和删除信号灯)。
事实上,为了获得我们特定操作所需要的#define定义,我们需要在包含sys/sem.h文件之前通常需要包含sys/types.h与sys/ipc.h文件。
相关的类型定义:
struct sembuf{
unsigned short sem_num; /* semaphore number *//*信号灯在信号灯集中的编号*/
short sem_op; /* semaphore operation *//*P操作或者V操作*/
short sem_flg; /* operation flags */
};
//这个联合体需要在程序声明,用于semctl函数的SETVAL选项的传值,作为第四个参数。
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
}
demo
进程间利用共享内存机制通信,一个进程写,一个进程读,用信号灯同步。
//writer.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define R 0
#define W 1
#define N 1024
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;
};
void pv(int semid, int op, int num)
{
struct sembuf buf;
buf.sem_num = num;//信号灯编号
buf.sem_op = op; //p操作或者v操作
buf.sem_flg = 0;
/*semid为信号灯集id, buf为struct sembuf结构体指针, 1表示操作信号灯的个数为1,如果大于一,表示操纵多个(则buf为struct sembuf结构体的数组指针)*/
if (semop(semid, &buf, 1) == -1)
{
perror("semop");
exit(-1);
}
}
int main()
{
int semid, shmid;
key_t key;
char *shmaddr;
if ((key = ftok(".", 'a')) == -1)
{
perror("ftok");
exit(-1);
}
//先启动的进程负责进行初始化,信号灯集中由两个信号灯,一个为读,一个为写
if ((semid = semget(key, 2, 0666 | IPC_CREAT | IPC_EXCL)) == -1)
{
if (errno == EEXIST)
{
semid = semget(key, 2, 0666);
}
}
else //first
{
union semun un;
un.val = 0;
//读的信号灯值为0
if (semctl(semid, R, SETVAL, un) == -1)
{
perror("init R");
exit(-1);
}
//写的信号灯值为1
un.val = 1;
if (semctl(semid, W, SETVAL, un) == -1)
{
perror("init R");
exit(-1);
}
}
//创建共享内存
if ((shmid = shmget(key, N, 0666 | IPC_CREAT)) == -1)
{
perror("shmget");
exit(-1);
}
//映射共享内存
if ((shmaddr = (char *)shmat(shmid, NULL, 0)) == (char *)-1)
{
perror("shmaddr");
exit(-1);
}
while (1)
{
//p(w) fgets v(r)
pv(semid, -1, W);
fgets(shmaddr, N, stdin);
pv(semid, 1, R);
if (strncmp(shmaddr, "quit", 4) == 0)
break;
}
usleep(100000);
if(semctl(semid, 0, IPC_RMID) == -1)
{
perror("rm sem");
exit(-1);
}
if (shmdt(shmaddr) == -1)
{
perror("shmdt");
exit(-1);
}
if (shmctl(shmid, IPC_RMID, NULL) == -1)
{
perror("shmctl");
exit(-1);
}
exit(0);
}
//reader.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define R 0
#define W 1
#define N 1024
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;
};
void pv(int semid, int op, int num)
{
struct sembuf buf;
buf.sem_num = num;
buf.sem_op = op;
buf.sem_flg = 0;
if (semop(semid, &buf, 1) == -1)
{
perror("semop");
exit(-1);
}
}
int main()
{
int semid, shmid;
key_t key;
char *shmaddr;
if ((key = ftok(".", 'a')) == -1)
{
perror("ftok");
exit(-1);
}
if ((semid = semget(key, 2, 0666 | IPC_CREAT | IPC_EXCL)) == -1)
{
if (errno == EEXIST)
{
semid = semget(key, 2, 0666);
}
}
else //first
{
union semun un;
un.val = 0;
if (semctl(semid, R, SETVAL, un) == -1)
{
perror("init R");
exit(-1);
}
un.val = 1;
if (semctl(semid, W, SETVAL, un) == -1)
{
perror("init R");
exit(-1);
}
}
if ((shmid = shmget(key, N, 0666 | IPC_CREAT)) == -1)
{
perror("shmget");
exit(-1);
}
if ((shmaddr = (char *)shmat(shmid, NULL, 0)) == (char *)-1)
{
perror("shmaddr");
exit(-1);
}
srandom(getpid());
while (1)
{
//p(r) printf v(w)
pv(semid, -1, R);
printf("%s", shmaddr);
if (strncmp(shmaddr, "quit", 4) == 0)
{
//v(r)
pv(semid, 1, R);
break;
}
pv(semid, 1, W);
sleep(random()%5+1);
}
if (shmdt(shmaddr) == -1)
{
perror("shmdt");
exit(-1);
}
exit(0);
}
转载地址:https://blog.csdn.net/weixin_42166105/article/details/116678342 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!