
正文
【linux高级程序设计】(第十一章)System V进程间通信 3
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
信号量通信机制
可以看到,跟消息队列类似,也是包括两个结构。
int semget (key_t __key, int __nsems, int __semflg) : 创建信号量集合
第一个参数:ftok产生的key值
第二个参数:创建的信号量个数
第三个参数:权限信息
创建信号量例子:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/types.h> int main(int argc, char * argv[])
{
int sem;
key_t key;
if((key = ftok(".",'B'))==-)
{
perror("ftok");
exit(EXIT_FAILURE);
}
if((sem = semget(key, , IPC_CREAT|)) == -)
{
perror("semget");
exit(EXIT_FAILURE);
}
printf("sem1 id is: %d\n", sem);
semctl(sem, , IPC_RMID, (struct msquid_ds*)); //删除信号量集合
return ;
}
int semctl (int __semid, int __semnum, int __cmd, ...) :控制信号量集合、信号量
第一个参数:要操作的信号量集合标识
第二个参数:信号量编号。如果操作整个信号量集合无意义;如果是某个信号量,为信号量下标。
第三个参数:执行的操作。 如果对整个集合操作,则包括:IPC_RMID, IPC_SET, IPC_STAT, IPC_INFO
如果是对某个或某些信号量操作,则包括GETPID、GETVAL、GETALL、GETNCNT、GETZCNT、SETVAL、SETALL.具体见图
设置读取信号量的例子
#include<stdio.h>
#include<sys/types.h>
#include<sys/sem.h>
#include<errno.h>
#define MAX_SEMAPHORES 5
int main(int argc, char *argv[])
{
int i, ret, semid;
unsigned short sem_array[MAX_SEMAPHORES];
unsigned short sem_read_array[MAX_SEMAPHORES];
union senmun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
//创建信号量集合
semid = semget(IPC_PRIVATE, MAX_SEMAPHORES, IPC_CREAT|);
if(semid != -)
{
//初始化
for(i = ; i < MAX_SEMAPHORES; i++)
sem_array[i] = (unsigned short)(i + );
arg.array = sem_array;
//设置所有信号量的值
ret = semctl(semid, , SETALL, arg);
if(ret == -)
printf("SETALL failed (%d)\n", errno); arg.array = sem_read_array;
//获取所有信号量的值
ret = semctl(semid, , GETALL, arg); //获取所有信号量的值
if(ret == -)
printf("GETALL failed (%d)\n", errno); for(i = ; i < MAX_SEMAPHORES; i++)
printf("Semaphore %d, value %d\n", i, sem_read_array[i]); //逐次获取信号量值
for(i = ; i < MAX_SEMAPHORES; i++)
{
ret = semctl(semid, i, GETVAL);
printf("Semaphore %d, value %d\n", i, sem_read_array[i]);
}
//删除信号量集合
ret = semctl(semid, , IPC_RMID);
}
else
{
printf("Could not allocate semaphore (%d)\n", errno);
}
return ;
}
int semop (int __semid, struct sembuf *__sops, size_t __nsops) :操作信号量
第一个参数:要操作的信号量集合ID
第二个参数
struct sembug{
unsigned short sem_num;
short sem_op;
short sem_flg;
};
- sem_num :操作的信号量编号
- sem_op :用于信号量的操作,正数表示增加信号量的值;负数表示减小信号量的值;0表示测试当前值是否为0
- sem_flg :操作标识,IPC_NOWAIT,如果等待立即返回;SEM_UNDO,当进程退出后,该进程对sem进行的操作将被撤销。
下面的代码,对信号量1做P操作(get),对信号量2做V操作(release)
struct sembuf sops[];
sops[].sem_num = ;
sops[].sem_op = -;
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = ;
sops[].sem_flg = ; semop(mysemid, sops, )
信号量解决生产者消费者问题,设有100个空位的缓冲池。
下面代码,经验证可用。
生产者代码:
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<errno.h>
int sem_id;
void init()
{
key_t key;
int ret;
unsigned short sem_array[];
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
key = ftok(".",'s');
sem_id = semget(key, , IPC_CREAT|);
sem_array[] = ; //0号下标 生产者
sem_array[] = ;
arg.array = sem_array;
ret = semctl(sem_id, , SETALL, arg); //初始化
if(ret == -)
printf("SETALL failed (%d)\n", errno);
printf("productor init is %d\n", semctl(sem_id, , GETVAL));
printf("space init is %d\n\n", semctl(sem_id, , GETVAL));
}
void del()
{
semctl(sem_id, , IPC_RMID);
}
int main(int argc, char *argv[])
{
struct sembuf sops[]; sops[].sem_num = ;
sops[].sem_op = ; //生产者数量加一
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = -; //消费者数量减一
sops[].sem_flg = ; init();
printf("this is productor\n");
while()
{
printf("\n\nbefore produce:\n");
printf("productor number is %d\n", semctl(sem_id, , GETVAL));
printf("space init is %d\n\n", semctl(sem_id, , GETVAL));
semop(sem_id, (struct sembuf *)&sops[], ); //先预定一个空位
printf("now producing.....\n");
semop(sem_id,(struct sembuf *)&sops[], ); //生产出一个产品 释放一个产品
printf("\nafter produce:\n");
printf("productor number is %d\n", semctl(sem_id, , GETVAL));
printf("space number is %d\n", semctl(sem_id, , GETVAL));
sleep();
}
del();
}
消费者代码:
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<errno.h>
int sem_id;
void init()
{
key_t key;
key = ftok(".", 's');
sem_id = semget(key, , IPC_CREAT|);
}
int main(int argc, char *argv[])
{
init();
struct sembuf sops[]; sops[].sem_num = ;
sops[].sem_op = -; //产品数量减一
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = ; //空位数量加一
sops[].sem_flg = ;
printf("this is customer\n"); while()
{
printf("\n\nbefore consume:\n");
printf("productor is %d\n", semctl(sem_id, , GETVAL));
printf("space is %d\n", semctl(sem_id, , GETVAL));
semop(sem_id, (struct sembuf *)&sops[], ); //预定一个要消费的产品
printf("now consuming.....\n");
semop(sem_id,(struct sembuf *)&sops[], ); //增加一个空位
printf("\nafter consume:\n");
printf("productor is %d\n", semctl(sem_id, , GETVAL));
printf("space is %d\n", semctl(sem_id, , GETVAL));
sleep();
}
}







