1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<linux/sem.h>//信号量的头文件 5 #include<errno.h> 6 #define SEM_PATH "/home/wangguolong/" 7 #define max_tries 3 8 int semid; 9 int main(void) 10 { 11 int flag1,flag2,key,i,init_ok,tmperrno;
1 /* 2 结构体 semid_ds 3 用于记录信号量集的各种信息0 4 struct semid_ds 5 { 6 struct ipc_perm sem_perm;//操作权限结构 7 struct sem *sem_base;//第一个信号量的信息 8 unsigned short sem_nsems;//信号量的数目 9 time_t sem_otime;//最终操作时间 10 time_t sme_ctime;//最终更改时间 11 }; 12
1 struct ipc_perm { 2 uid_t uid; //IPC对象owner's euid 3 gid_t gid; // owner's egid 4 uid_t cuid; //creator's euid 5 gid_t cgid; //creator's egid 6 mode_t mode; //权限 0400|0200 | 0040|0020 |0004|0002; 7 key_t key; };
13 struct sem 14 { 15 unsigned short semval;//信号量的值,一般≥0 16 pid_t sempid;//最终操作的pid 17 unsigned short semncent;//信号量的值大于currval值的进程个数 18 unsigned short semzcnt;//信号量的值为0时的进程个数 19 20 }; 24 *
12struct semid_ds sem_info;
1 /* 4 struct seminfo { 5 int semmap;//信号图条目的数量 6 int semmni;//最大信号标识符号码 7 int semmns;//在系统信号量的MAS数 8 int semmnu;//撤消结构系统的数目是 9 int semmsl;//最大信号每半数 10 int semopm;//最大的行动电话号码是每个信号量操作 11 int semume;//每个进程的撤销项的最大数目 12 int semusz;//结构sem_undo的比特数 13 int semvmx;//最大信号值 14 15 }; 16 17 */
13struct seminfo sem_info2;
1 /* 2 联合体semun 3 4 union semun 5 { 6 int val; val的值 7 struct semid_ds *buf;//供IPC_STAT 和IPC_SET使用 8 unsigned short array;/供GETALL和SETALL使用 9 } 13 */
14 union semun arg;
1 /* 2 sembuf结构体 3 4 struct sembuf 5 { 6 unsigned short sem_num;//将要操作的信号量 7 short sem_op;//所要执行的操作 8 short sem_flg;//semop的行为 9 } 10 */
15struct sembuf askfor_res,free_res;
16 flag1=IPC_CREAT|IPC_EXCL|00666; 17 flag2=IPC_CREAT|00666; 18 key=ftok(SEM_PATH,'a'); 19 if(key==-1) 20 { 21 perror("ftok error!"); 22 exit(1); 23 } 24 25 init_ok=0;
1 /* 2 semget函数 3 4 头文件及定义: 5 #include<sys/types.h> 6 #include<sys/ipc.h> 7 #include<sys/shm.h> 8 int semget(key_t key,int nsems,int flag); 9 10 参数: 11 key 键值 12 nesems 创建的信号量集中包含的信号量的个数 13 flag 操作类型 和共享内存的操作一样 14 15 返回值: 创建成功返回信号集ID,创建失败返回-1
*/
26 semid=semget(key,1,flag1);//创建一个新的信号量集,其中只包含一个信号量 27 28 if(semid<0) 29 { 30 tmperrno=errno; 31 perror("semget"); 32 33 if(tmperrno==EEXIST) 34 { 35 semid=semget(key,1,flag2); 36 arg.buf=&sem_info; 37 for(i=0;i<max_tries;i++) 38 { 39 if(semctl(semid,0,IPC_STAT,arg)==-1) 40 { 41 perror("semctl error"); 42 i=max_tries; 43 } 44 else 45 { 46 if(arg.buf->sem_otime!=0) 47 { 48 init_ok=1; 49 } 50 else 51 sleep(1); 52 53 } 54 } 55 56 if(!init_ok) 57 { 58 arg.val=1; 59 if(semctl(semid,0,SETVAL,arg)==-1) 60 perror("semctl setval error"); 61 } 62 } 63 else 64 { 65 perror("semget error ,process exit"); 66 exit(1); 67 } 68 } 69 else 70 { 71 arg.val=1;
1 /* 2 semctl 信号量集控制函数 3 4 头文件及定义 5 #include<sys/types.h> 6 #include<sys/ipc.h> 7 #include<sys/shm.h> 8 int semctl(int semid,int semnum,int cmd,union semun arg); 9 10 11 参数: 12 semid 信号量集的标识符 13 semnum 指定操作的信号量,相当于信号量集中的下表 14 cmd 要执行的操作 和 arg 配合使用 15 16 cmd取值 含义 17 GETALL 获得信号量集semid中信号量的个数,并将该值赋给无符号短整数 arg.array 18 GETVAL 获得信号量集semid中semnum所指定的信号量的值semval 19 SETVAL 将arg.val的值赋给semval 20 */
72if(semctl(semid,0,SETVAL,arg)==-1)
73 perror("semctl setval error");
74 }
75
76 arg.buf=&sem_info; 77 if(semctl(semid,0,IPC_STAT,arg)==-1) 78 { 79 perror("semctl IPC STAT"); 80 } 81 printf("owner's uid is %d\n",arg.buf->sem_perm.uid); 82 printf("owner's gid is %d\n",arg.buf->sem_perm.gid); 83 printf("creater's uid is %d\n",arg.buf->sem_perm.cuid); 84 printf("creater's gid is %d\n",arg.buf->sem_perm.cgid); 85 arg.__buf=&sem_info2; 86 if(semctl(semid,0,IPC_INFO,arg)==-1)//获取信号量的信息 87 perror("semctl IPC_INFO"); 88 89 printf("the number of entries in semaphore map is %d\n",arg.__buf->semmap); 90 printf("max number of semaphore identifiers is %d\n",arg.__buf->semmni); 91 printf("mas number of semaphores in system is %d\n",arg.__buf->semmns); 92 printf("the number of undo structures system wide is %d\n",arg.__buf->semmnu); 93 printf("max number of semaphores per semid is %d\n",arg.__buf->semmsl); 94 printf("max number of ops per semop call is %d\n",arg.__buf->semopm); 95 printf("max number of undo entries per process is %d\n",arg.__buf->semume); 96 printf("the size of struct sem_undo is %d\n",arg.__buf->semusz); 97 printf("the maximum semaphore value is %d\n",arg.__buf->semvmx); 98 99 askfor_res.sem_num=0; 100 askfor_res.sem_op=-1; 101 askfor_res.sem_flg=SEM_UNDO;
1 /* 2 semop函数 3 作用:对信号量集进行操作 4 5 头文件及函数原型: 6 #include<sys/types.h> 7 #include<sys/ipc.h> 8 #include<sys/shm.h> 9 int semop(int semid,struct sembuf semoparray[],size_t nops); 10 11 参数: 12 semid 所要操作的信号量集标识符 13 nops 指明了参数所要指向的数组的元素个数 14 参数 semoparray 用来说明所要执行的操作,由于此函数是原子操作,一旦执行就执行数组中的所有操作: 15 16 struct sembuf 17 { 18 unsigned short sem_num; 19 short sem_op; 20 short sem_flg; 21 } 22 23 参数定义: 24 sem_num是对应的信号量中的某一个资源(即指定要进行操作的信号量), 25 sem_op 是要执行的操作 26 sem_flg 是semop的行为 27 28 其中 sem_op的取值和对应的操作如下: 29 sem_op >0 表示进程对资源使用完毕,释放相应的资源数,并将sem_op的值加到信号量的值上 30 sem_op=0 进程阻塞直到信号量的相应值为0 31 sem_op<0 请求sem_op 的绝对值资源。 32 */
SEM_UNDO //程序结束时(不论正常或不正常),保证信号值会被重设为semop()调用前的值。这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。
102 if(semop(semid,&askfor_res,1)==-1) 103 perror("semop error"); 104 sleep(3); 105 printf("now free the resource\n"); 106 107 free_res.sem_num=0; 108 free_res.sem_op=1; 109 free_res.sem_flg=SEM_UNDO; 110 if(semop(semid,&free_res,1)==-1) 111 if(errno==EIDRM) 112 printf("The senaophore set was removed\n"); 113 114 if(semctl(semid,0,IPC_RMID)==-1) 115 perror("semctl IPC_RMID"); 116 else 117 printf("remove sem ok\n"); 118 119 return 0; 120 }