一、System V 信号量
1.信号量linux命令
显示:
ipcs -a 显示所有共享内核对象
ipcs -s 显示信号量 s = semphore删除:
ipcrm -s ID 删除信号量
二、主要函数应用
1. 函数原型:
#include <sys/sem.h>
int semget(key_t key, int nsems, int flag);
参数:
- key:信号集的名字
- nsems:信号集中信号量的个数
- semflg:由九个权限标志构成,它们的用法和创建文件时用的mode模式标志是一样的。
2. 函数原型:
#include <sys/sem.h>
int semctl(int semid. int semnum, int cmd, ..../*union semun arg*/);
参数:
- semid:由semget返回的信号集标识码
- semnum:信号集中信号量的序号
- cmd:将要采取的动作(有三个可能取值)
- 最后一个参数根据命令不同而不同
cmd:
命令 | 说明 |
---|---|
SETVAL | 设置信号量集中信号量的计数值 |
GETVAL | 获取信号集中的信号量的计数值 |
IPC_STAT | 对此集合取semid_ds结构,并存储在arg.buf指向的结构中 |
IPC_SET | 在进程有足够权限的前提下,把信号集中的当前关联值设置为semid_ds 数据结构中给出的值 |
IPC_RMID | 删除信号集 |
3. 函数原型:
#include <sys/sem.h>
int semop(int semid, struct sembuf semoparray[], size_t nops);
参数:
- semid:是该信号集量的标识码ID,也是semget函数的返回值。
- sops:是一个指向结构体的指针
- nsops:操作的信号量的个数
三、程序清单
#include <sys/sem.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>#define ERR_EXIT(m) do { perror(m), exit(EXIT_FAILURE); }while(0)
union semun
{int val;struct semid_ds *buf;unsigned short *array;
};int sem_creat(key_t key)
{int semid;semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);if (semid == -1)ERR_EXIT("semget");return semid;
}int sem_open(key_t key)
{int semid;semid = semget(key, 0, 0);if (semid == -1)ERR_EXIT("semget");return semid;
}int sem_setval(int semid, int val)
{union semun su;su.val = val;int ret;ret = semctl(semid, 0, SETVAL, su);if (ret == -1)ERR_EXIT("sem_setval");return 0;
}
int sem_getval(int semid)
{int ret;ret = semctl(semid, 0, GETVAL, 0);if (semid == -1)ERR_EXIT("sem_getval");printf("current val is %d\n", ret);return ret;
}int sem_d(int semid)
{int ret;ret = semctl(semid, 0, IPC_RMID, 0);if (ret == -1)ERR_EXIT("semctl");return 0;
}int sem_p(int semid)
{struct sembuf sb = { 0, -1, 0 };int ret;ret = semop(semid, &sb, 1);if (ret == -1)ERR_EXIT("semop"); return ret;
}int sem_v(int semid)
{struct sembuf sb = { 0, 1, 0 };int ret;ret = semop(semid, &sb, 1);if (ret == -1)ERR_EXIT("semop"); return ret;
}int sem_getmode(int semid)
{union semun su;struct semid_ds sem;su.buf = &sem;int ret = semctl(semid, 0, IPC_STAT, su);if (ret == -1)ERR_EXIT("semctl");printf("currcnt pcrmissions id %o\n", su.buf->sem_perm.mode);return ret;
}int sem_setmode(int semid, char *mode)
{union semun su;struct semid_ds sem;su.buf = &sem;int ret = semctl(semid, 0, IPC_STAT, su);if (ret == -1)ERR_EXIT("semctl");printf("cuttent permissions is %o\n", su.buf->sem_perm.mode);sscanf(mode, "%o", (unsigned int*)&su.buf->sem_perm.mode);ret = semctl(semid, 0, IPC_SET, su);if (ret == -1)ERR_EXIT("semctl");printf("permissins updated...\n");
}void usage(void)
{fprintf(stderr, "usage\n");fprintf(stderr, "semtool -c\n");fprintf(stderr, "semtool -d\n");fprintf(stderr, "semtool -p\n");fprintf(stderr, "semtool -v\n");fprintf(stderr, "semtool -s <val>\n");fprintf(stderr, "semtool -q\n");fprintf(stderr, "semtool -f\n");fprintf(stderr, "semtool -m <mode>\n");
}int main(int argc, char *argv[])
{int opt;opt = getopt(argc, argv, "cdpvs:gfm:");if (opt == '?')exit(EXIT_FAILURE);if (opt == -1){usage();exit(EXIT_FAILURE);}key_t key = ftok(".", 's');int semid;switch (opt){case'c':sem_creat(key);break;case'p':semid = sem_open(key);sem_p(semid);sem_getval(semid);break;case'v':semid = sem_open(key);sem_v(semid);sem_getval(semid);break;case'd':semid = sem_open(key);sem_d(semid);break;case's':semid = sem_open(key);sem_setval(semid, atoi(optarg));break;case'g':semid = sem_open(key);sem_getval(semid);break;case'f':semid = sem_open(key);sem_getmode(semid);break;case'm':semid = sem_open(key);sem_setmode(semid, argv[2]);break;}return 0;
}
四、参考资料
- getopt函数用法