版权声明: https://blog.csdn.net/dashoumeixi/article/details/84627088
SysV 信号量集 : 一个信号量数组; 命令 ipcs - s 查看
//这个联合体 有些linux系统中没定义. 其实可用可不用
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) */
};
semget : 创建或获取一个信号量集 . 第2个参数, 指定N个信号量;
semop: 修改一个或一批信号量. 相当于 posix 中的 sem_wait 和 sem_post 综合体
每个信号量由struct sembuf 控制.
sem_num 表示第N个信号量.
sem_op 可以是 > 0 , 0 , <0 , 相当于 sem_post == 1, sem_wait == -1;
sem_flg : IPC_NOWAIT 不阻塞, SEM_UNDO 还原;
sem_ctl : 给信号量赋值, 删除, 状态等
SEM_UNDO: 如果指定了. 不论当前进程是否正常退出 都将还原此操作的 sem_op 值. 用于以防万一异常结束的进程
如果是生产者/消费者的情况,则不应该使用
比如:
if(0== fork()){
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
semop(semid,&sem,1)
/*
一般正常的还原操作; 如果指定了SEM_UNDO 则不写也没关系.子进程结束后将还原;
sem.sem_op = 1;
semop(semid,&sem,1);
*/
exit(0);
}
当这段代码执行完后. 由于SEM_UNDO,进程被回收前 相当于将执行 被注释的代码;
SEM_UNDO 用于以防万一,异常结束的进程;
semcreate.c
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
int main(int argc ,char** argv ,char ** env)
{
if(argc != 3){
puts("pathname nsems");
return 0;
}
int nsems = atoi(argv[2]);
int key = ftok(argv[1],0);
//创建一个信号量集 , 包含 nsems 个信号量
int semid = semget(key,nsems,IPC_CREAT|0644);
printf("nsems:%d , key:%d,semid:%d\n", nsems, key,semid);
return 0;
}
semsetvalue.c
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
int main(int argc ,char** argv ,char ** env)
{
if(argc < 2){
puts("pathname semvalues[max nsems]");
return 0;
}
//获取信号量集
int semid = semget(ftok(argv[1],0),0,0);
printf("semid:%d\n" , semid);
struct semid_ds semstat = {0};
//获取信号量状态
semctl(semid,0,IPC_STAT,&semstat);
//信号量个数
int nsems = semstat.sem_nsems;
printf("nsems : %d\n" , nsems);
//分配内存给信号量赋值
unsigned short * ptr = calloc(nsems,sizeof(unsigned short));
for(int i =0 ; i < nsems; ++i)
ptr[i]= atoi(argv[i+2]);
// SETALL 一起赋值 , SETVAL 单个赋值
if(semctl(semid,0,SETALL,ptr) < 0)
perror("set values failed");
else
puts("set values success");
return 0;
}
semgetvalue.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc ,char** argv ,char ** env)
{
if(argc != 2){
puts("pathname");
return 0;
}
int key = ftok(argv[1],0);
// 获取
int semid = semget(key,0,0);
printf("semid:%d\n" , semid);
struct semid_ds semidbuf = {0};
//获取信号量数量
semctl(semid,0,IPC_STAT,&semidbuf);
printf(" sem nums : %ld\n" , semidbuf.sem_nsems);
//分配内存
unsigned short * array = calloc(semidbuf.sem_nsems,sizeof(unsigned long));
//获取所有的信号量值
semctl(semid,0,GETALL,array);
for(int i = 0 ; i < semidbuf.sem_nsems; ++i)
printf("semval[%d]=%d\n" , i, array[i]);
free(array);
return 0;
}
semop.c
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
int main(int argc ,char** argv ,char ** env)
{
if(argc < 2){
puts("pathname -n[IPC_NOWAIT] -u[SEM_UNDO] operation");
return 0;
}
char ** p = argv;
int flag = 0;
//提取是否需要 IPC_NOWAIT , SEM_UNDO 的参数
while(*p){
if(strcmp(*p,"n") == 0 || strcmp(*p,"-n") == 0) {
flag |= IPC_NOWAIT;
}
if(strcmp(*p,"u") == 0 || strcmp(*p,"-u") == 0) {
flag |= SEM_UNDO;
}
*p++;
}
//sem_op 的数量
int count = argc - 2;
// sem_op 的起始位置
int oper_index = 2;
if(flag & IPC_NOWAIT) {--count; ++oper_index;}
if(flag & SEM_UNDO) {--count;++oper_index;}
//获取信号量集
int semid = semget(ftok(argv[1],0),0,0);
printf("semid:%d\n" , semid);
struct semid_ds semstat = {0};
//获取信号量数量
semctl(semid,0,IPC_STAT,&semstat);
//获取最多可操作数
int nsems = semstat.sem_nsems > count ? count :semstat.sem_nsems ;
printf("input n:%d, sem num : %d ,nsems:%d, operindex:%d\n",
count,semstat.sem_nsems,nsems,oper_index);
struct sembuf *ptr = 0;
//分配内存
ptr = calloc(nsems, sizeof(struct sembuf));
//赋值操作
for(int i = 0 ; i < nsems; ++i){
ptr[i].sem_num = i;
ptr[i].sem_op = atoi(argv[oper_index+i]);
ptr[i].sem_flg = flag;
printf("ptr[%d]=%d\n" , i,ptr[i].sem_op);
}
if(semop(semid,ptr,nsems) < 0)
perror("semop failed");
else
puts("success");
return 0;
}