5.4 SYSV进程通信之信号灯集
sem.c
1 /*摘自:信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。 2 * 信号量:就是用来解决进程间的同步与互斥问题的一种进程间通信机制。 3 * 4 * 信号灯集:一组信号量的集合,信号灯进行两个进程同步的操作和信号量完成的功能是一样的, 5 * 但两者操作方式标准不同: 6 * 信号量(POSIX) 7 * 信号灯(SYSV) 8 * 9 * PV原子操作的具体定义如下:(好好理解,很重要的啊) 10 * P操作:如果有可用的资源(信号量值>0),则此操作所在的进程占用一个资源(此时信号量值减1,进入临界区代码); 11 * 如果没有可用的资源(信号量值=0),则此操作所在的进程被阻塞直到系统将资源分配给该进程(进入等待队列,一直等到资源轮到该进程)。 12 * 13 * V操作:如果在该信号量的等待队列中有进程在等待资源,则唤醒一个阻塞进程;如果没有进程等待它, 14 * 则释放一个资源(即信号量值加1)。 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <error.h> 21 #include <errno.h> 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 #include <sys/ipc.h> 25 #include <sys/sem.h> 26 27 #define error_exit(_errmsg_) error(EXIT_FAILURE,errno,_errmsg_) 28 29 #define w 0 30 #define r 1 31 32 union semun { 33 int val; /* Value for SETVAL */ 34 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 35 unsigned short *array; /* Array for GETALL, SETALL */ 36 struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ 37 }; 38 39 /*初始化一个信号灯中所有的信号量*/ 40 int init_sem(int semid,int *array,int len) 41 { 42 union semun myun; 43 int i = 0; 44 for(i = 0;i < len;i++) 45 { 46 myun.val = array[i]; 47 if(-1 == (semctl(semid,i,SETVAL,myun))) 48 error_exit("fail to semctl!"); 49 } 50 return 0; 51 } 52 53 /* 操作一个信号量,让其完成申请/释放资源的操作 54 * int semop(int semid, struct sembuf *sops, unsigned nsops); 55 * semid: 56 * struct sembuf *sops;对信号灯操作方式的集合 57 * nsops: 信号量操作的个数 58 * 成功返回0;失败返回-1. 59 * 60 * */ 61 62 //P操作:申请资源的操作 63 int sem_p(int semid,int num,int n) 64 { 65 struct sembuf mybuf; 66 67 mybuf.sem_num = num; 68 mybuf.sem_op = -1; 69 mybuf.sem_flg = SEM_UNDO; 70 if(-1 == semop(semid,&mybuf,n)) 71 error_exit("fail to semop!"); 72 return 0; 73 } 74 75 //V操作:释放资源的操作 76 int sem_v(int semid,int num,int n) 77 { 78 struct sembuf mybuf; 79 80 mybuf.sem_num = num; 81 mybuf.sem_op = +1; 82 mybuf.sem_flg = SEM_UNDO; 83 if(-1 == semop(semid,&mybuf,n)) 84 error_exit("fail to semop!"); 85 return 0; 86 } 87 88 89 int main(void) 90 { 91 key_t key; 92 if(-1 == (key = ftok(".",'a'))) 93 error_exit("fail to ftok!"); 94 /*创建一信号灯 95 *int semget(key_t key, int nsems, int semflg); 96 *参数: 97 key:键值 98 nsem: 该信号灯中信号量的个数 99 semflg:IPC_CREAT 100 IPC_EXCL 101 成功返回信号灯的ID号,失败返回-1 102 * */ 103 int semid = 0; 104 int a[2] = {1,0}; 105 106 if(-1 == (semid = semget(key,2,IPC_CREAT | 0644))) 107 error_exit("fail to semget!"); 108 109 /* 对信号灯中的信号量进行相应的操作/发命令 110 * int semctl(int semid, int semnum, int cmd, ...); 111 * 参数: 112 * semid:信号灯ID号 113 * semnum:信号灯中信号量的下标 114 * cmd: SETVAL: 设置信号灯中信号量的值 115 * IPC_RMID:删除信号灯 116 * IPC_SET: 117 * IPC_STAT: 118 * 成功返回0;失败返回-1. 119 */ 120 init_sem(semid,a,2); 121 122 sem_p(semid,w,1); 123 printf("申请到了写资源...\n"); 124 125 sem_v(semid,r,1); 126 printf("释放到了读资源...\n"); 127 128 sem_p(semid,r,1); 129 printf("申请到了读资源...\n"); 130 131 semctl(semid,0,IPC_RMID); 132 return 0; 133 }
浙公网安备 33010602011771号