System V信号量
来源:互联网 发布:java模拟上传文件 编辑:程序博客网 时间:2024/06/11 06:32
二值信号量 : 其值只有0、1 两种选择,0表示资源被锁,1表示资源可用;
计数信号量:其值在0 和某个限定值之间,不限定资源数只在0 1 之间;
计数信号量集 :多个信号量的集合组成信号量集
创建一个信号量或访问一个已经存在的信号量集。
int semget(key_t key, int nsems, int semflg);
该函数执行成功返回信号量标示符,失败返回-1
参数key是通过调用ftok函数得到的键值,nsems代表创建信号量的个数,如果只是访问而不创建则可以指定该参数为0,我们一旦创建了该信号量,就不能更改其信号量个数,只要你不删除该信号量,你就是重新调用该函数创建该键值的信号量,该函数只是返回以前创建的值,不会重新创建;
semflg 指定该信号量的读写权限,当创建信号量时不许加IPC_CREAT ,若指定IPC_CREAT |IPC_EXCL则创建是存在该信号量,创建失败。
打开一个信号量集后,对其中一个或多个信号量的操作。
int semop(int semid, struct sembuf *sops, unsigned nsops);
该函数执行成功返回0,失败返回-1;
第一个参数semid 为信号量标示符;nops为第二个参数的操作数组的个数,第二个参数sops为一个结构体数组指针,结构体定义在sys/sem.h中,结构体如下
struct sembuf { unsigned short sem_num; /* semaphore index in array */ short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */};sem_num 操作信号的下标,其值可以为0 到nops
sem_flg为该信号操作的标志:其值可以为0、IPC_NOWAIT 、 SEM_UNDO
0 在对信号量的操作不能执行的情况下,该操作阻塞到可以执行为止;
IPC_NOWAIT 在对信号量的操作不能执行的情况下,该操作立即返回;
SEM_UNDO当操作的进程推出后,该进程对sem进行的操作将被取消;
sem_op取值 >0 则信号量加上它的值,等价于进程释放信号量控制的资源
sem_op取值 =0若没有设置IPC_NOWAIT, 那么调用进程将进入睡眠状态,直到信号量的值为0,否则进程直接返回
sem_op取值 <0则信号量加上它的值,等价于进程申请信号量控制的资源,若进程设置IPC_NOWAIT则进程再没有可用资源情况下,进程阻塞,否则直接返回。
对信号量执行各种控制操作。
int semctl(int semid, int semnum, int cmd, ...);
该函数执行成功返回非负值,失败返回-1
参数semid为信号集的标识符,参数 semnum标识一个特定信号,该参数仅用于 SETVAL、GETVAL、GETPID命令
看一个例子:这个范例使用信号灯来同步共享内存的操作, 程序创建一块共享内存, 然后父子进程共同修改共享内存. 父子进程采用信号灯来同步操作.
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#define SHM_KEY 0x33#define SEM_KEY 0x44union semun { int val; struct semid_ds *buf; unsigned short *array;};int P(int semid){ struct sembuf sb; sb.sem_num = 0; sb.sem_op = -1; sb.sem_flg = SEM_UNDO; if(semop(semid, &sb, 1) == -1) { perror("semop"); return -1; } return 0;}int V(int semid){ struct sembuf sb; sb.sem_num = 0; sb.sem_op = 1; sb.sem_flg = SEM_UNDO; if(semop(semid, &sb, 1) == -1) { perror("semop"); return -1; } return 0;}int main(int argc, char **argv){ pid_t pid; int i, shmid, semid; int *ptr; union semun semopts; /* 创建一块共享内存, 存一个int变量 */ if ((shmid = shmget(SHM_KEY, sizeof(int), IPC_CREAT | 0600)) == -1) { perror("msgget"); } /* 将共享内存映射到进程, fork后子进程可以继承映射 */ if ((ptr = (int *)shmat(shmid, NULL, 0)) == (void *)-1) { perror("shmat"); } *ptr = 0; /* 创建一个信号量用来同步共享内存的操作 */ if ((semid = semget(SEM_KEY, 1, IPC_CREAT | 0600)) == -1) { perror("semget"); } /* 初始化信号量 */ semopts.val = 1; if (semctl(semid, 0, SETVAL, semopts) < 0) { perror("semctl"); } if ((pid = fork()) < 0) { perror("fork"); } else if (pid == 0) { /* Child */ /* 子进程对共享内存加1 */ for (i = 0; i < 100000; i++) { P(semid); (*ptr)++; V(semid); printf("child: %d\n", *ptr); } } else { /* Parent */ /* 父进程对共享内存减1 */ for (i = 0; i < 100000; i++) { P(semid); (*ptr)--; V(semid); printf("parent: %d\n", *ptr); } waitpid(pid); /* 如果同步成功, 共享内存的值为0 */ printf("finally: %d\n", *ptr); } return 0;}
- 2、System V 信号量
- system V信号量
- 信号量(System V)
- System V 信号量
- System V 信号量2
- System V 信号量
- Linux System V 信号量
- System V 信号量(一)
- System V 信号量(二)
- 关于System V 信号量
- system V信号量
- System V信号量
- System V 信号量机制
- 信号量/灯(system V IPC)
- System V 信号量集理解
- System V信号量(1)
- System V信号量(2)
- System V信号量(3)
- Qt常用快捷键
- cocos2d-x 学习笔记
- Spark中的combineByKey
- 数据结构与算法 -排序
- 用 FragmentTabHost 实现底部菜单
- System V信号量
- OC-3-字符串
- Spark修炼之道(进阶篇)——Spark入门到精通:第十三节 Spark Streaming—— Spark SQL、DataFrame与Spark Streaming
- Android-利用SharedPreferences实现记住密码和账号功能
- 微信开发快速入门
- 安装及配置GoClipse
- iOS ---UICollection
- 海量数据处理
- mysql 5.7.9 安装问题