信号量通信机制
可以看到,跟消息队列类似,也是包括两个结构。
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‘))==-1) { perror("ftok"); exit(EXIT_FAILURE); } if((sem = semget(key, 3, IPC_CREAT|0770)) == -1) { perror("semget"); exit(EXIT_FAILURE); } printf("sem1 id is: %d\n", sem); semctl(sem, 0, IPC_RMID, (struct msquid_ds*)0); //删除信号量集合 return 0; }
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|0666); if(semid != -1) { //初始化 for(i = 0; i < MAX_SEMAPHORES; i++) sem_array[i] = (unsigned short)(i + 1); arg.array = sem_array; //设置所有信号量的值 ret = semctl(semid, 0, SETALL, arg); if(ret == -1) printf("SETALL failed (%d)\n", errno); arg.array = sem_read_array; //获取所有信号量的值 ret = semctl(semid, 0, GETALL, arg); //获取所有信号量的值 if(ret == -1) printf("GETALL failed (%d)\n", errno); for(i = 0; i < MAX_SEMAPHORES; i++) printf("Semaphore %d, value %d\n", i, sem_read_array[i]); //逐次获取信号量值 for(i = 0; i < MAX_SEMAPHORES; i++) { ret = semctl(semid, i, GETVAL); printf("Semaphore %d, value %d\n", i, sem_read_array[i]); } //删除信号量集合 ret = semctl(semid, 0, IPC_RMID); } else { printf("Could not allocate semaphore (%d)\n", errno); } return 0; }
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[4]; sops[0].sem_num = 1; sops[0].sem_op = -1; sops[0].sem_flg = 0; sops[1].sem_num = 2; sops[1].sem_op = 1; sops[1].sem_flg = 0; semop(mysemid, sops, 2)
信号量解决生产者消费者问题,设有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[2]; union semun { int val; struct semid_ds *buf; unsigned short *array; }arg; key = ftok(".",‘s‘); sem_id = semget(key, 2, IPC_CREAT|0644); sem_array[0] = 0; //0号下标 生产者 sem_array[1] = 100; arg.array = sem_array; ret = semctl(sem_id, 0, SETALL, arg); //初始化 if(ret == -1) printf("SETALL failed (%d)\n", errno); printf("productor init is %d\n", semctl(sem_id, 0, GETVAL)); printf("space init is %d\n\n", semctl(sem_id, 1, GETVAL)); } void del() { semctl(sem_id, 0, IPC_RMID); } int main(int argc, char *argv[]) { struct sembuf sops[2]; sops[0].sem_num = 0; sops[0].sem_op = 1; //生产者数量加一 sops[0].sem_flg = 0; sops[1].sem_num = 1; sops[1].sem_op = -1; //消费者数量减一 sops[1].sem_flg = 0; init(); printf("this is productor\n"); while(1) { printf("\n\nbefore produce:\n"); printf("productor number is %d\n", semctl(sem_id, 0, GETVAL)); printf("space init is %d\n\n", semctl(sem_id, 1, GETVAL)); semop(sem_id, (struct sembuf *)&sops[1], 1); //先预定一个空位 printf("now producing.....\n"); semop(sem_id,(struct sembuf *)&sops[0], 1); //生产出一个产品 释放一个产品 printf("\nafter produce:\n"); printf("productor number is %d\n", semctl(sem_id, 0, GETVAL)); printf("space number is %d\n", semctl(sem_id, 1, GETVAL)); sleep(4); } 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, 2, IPC_CREAT|0644); } int main(int argc, char *argv[]) { init(); struct sembuf sops[2]; sops[0].sem_num = 0; sops[0].sem_op = -1; //产品数量减一 sops[0].sem_flg = 0; sops[1].sem_num = 1; sops[1].sem_op = 1; //空位数量加一 sops[1].sem_flg = 0; printf("this is customer\n"); while(1) { printf("\n\nbefore consume:\n"); printf("productor is %d\n", semctl(sem_id, 0, GETVAL)); printf("space is %d\n", semctl(sem_id, 1, GETVAL)); semop(sem_id, (struct sembuf *)&sops[0], 1); //预定一个要消费的产品 printf("now consuming.....\n"); semop(sem_id,(struct sembuf *)&sops[1], 1); //增加一个空位 printf("\nafter consume:\n"); printf("productor is %d\n", semctl(sem_id, 0, GETVAL)); printf("space is %d\n", semctl(sem_id, 1, GETVAL)); sleep(3); } }
时间: 2024-10-11 21:26:21