1、源代码
/************************************************************************* > File Name: svsem_myls.c > Author:zhangshengshan > Mail: zsszsszsszss@126.com > show all the semophmore ************************************************************************/ #include<stdio.h> #include<sys/types.h> #include<stdlib.h> #include<sys/sem.h> #include "semun.h" #include <sys/ipc.h> int get_sem_index(int *pIndex,union semun *pSemun) { *pIndex = semctl(0,0,SEM_INFO,*pSemun); if (-1==*pIndex) { return -1; } return *pIndex; } int main(int argc,char * argv[]){ union semun union_sem; union semun arg; union semun dummy; struct semid_ds ds_sem; struct seminfo info_sem; int index=-1; int id_sem=0; int num_sem=0; int i=-1; int j=-1; int k=-1; union_sem.__buf=&info_sem; //arg.buf=&ds_sem; //从内核获取信号量的索引 if( -1==get_sem_index(&index,&union_sem)) { printf("get index failure!\n"); exit(1); } //show_semid(); printf("semid num sem# value SEMPID SEMNCNT SEMZCNT\n"); for (i=0;i<=index;i++) { arg.buf=&ds_sem; //获取信号集描述符 id_sem=semctl(i,0,SEM_STAT,arg); k=arg.buf->sem_nsems; //show every sem info in id_sem //member array is a pointor! arg.array=calloc(arg.buf->sem_nsems,sizeof(arg.array[0])); if (arg.array == NULL) { printf("calloc error!\n"); exit (9); } // here the param will be changed! because it is a union! if (semctl(id_sem,0,GETALL,arg)==-1) { printf("semctl-getALL\n"); exit(8); } printf("now arg.buf->sem_nsems is %d, and ds_sem.sem_nsems is %d\n",arg.buf->sem_nsems,ds_sem.sem_nsems); //printf("sem # value SEMPID SEMNCNT SEMZCNT\n"); for(j=0;/**/ j<k;j++) { printf("%5d %5d %3d %5d %5d %5d %5d\n",id_sem,k,j,arg.array[j],\ semctl(id_sem,j,GETPID,dummy),\ semctl(id_sem,j,GETNCNT,dummy),\ semctl(id_sem,j,GETZCNT,dummy)); } } return 0; }
2、程序运行结果
编译上述程序并且运行可以得到结果为:
这里,semid列表示信号集标识符号、每一个信号集合中可能有多个信号量。这里显示的图形表示163840信号集合现在有两个信号量,而信号集合196609中
包含三个信号量。
3、相关数据结构
3.1 union semun结构
在进行信号量相关编程的时候经常需要提供union semun共用体,该公用体需要用户自行实现。这里的semid_ds是描述信号量集合的结构体。
3.2 struct semid_ds结构体
该结构体描述了信号量集合的相关信息,其中sem_perm成员描述了该信号量集合的属性和权限,而sem_nsems成员则表示该信号量集合中具有多少成员。
4、semct()函数及相关标志
semctl函数提供了对信号量集合以及信号量的种种操作,上图的DESCRIPTION中清楚的描述了semtcl所需要的各个函数的含义。 我们在程序中使用了
*pIndex = semctl(0,0,SEM_INFO,*pSemun);
SEM_INFO标志同IPC_INFO 标志基本相同,在帮助手册中其描述如下:
可见其主要功能是返回seminfo的结构体,描述相关额信息,seminfo结构体可以在Linux下man semctl 查看。
那么这里的semctl返回的数值是什么含义呢?
可见在 使用了SEM_INFO的情况下,得到的返回值是 the index of the highest used entry in the kernel's internal array recording information about all semaphore sets(得到的是内核中记录所有信号量集合中最大的那个记录),关键是后面的的这句话比较关键,给出了如何获取信号量集合描述符号的方法,this information can be used with repeated SEM_STAT operations to obtain information about all semaphore sets on the system.
这里请注意在使用SEM_STAT获取相关信号量集合semctl函数的第一个参数semid不是通常意义下的信号量集合的标识符号(即不是通过semget()获取到的标识符号!),而是使用SEM_INFO标志semctl()获得的内核的符号。
5、程序整体思路
1、利用semctl()和SEM_INFO从内核获取系统中的信号量共有多少个?
*pIndex = semctl(0,0,SEM_INFO,*pSemun);
2、循环利用semctl()和SEM_STAT获取信号量集合的描述符号(这个描述符号对应semget()获取的信号集合的描述符号)
id_sem=semctl(i,0,SEM_STAT,arg);
3、循环利用semctl()和GETALL获取每个信号集合中的所有信号量的信息,并且打印相关信息。
if (semctl(id_sem,0,GETALL,arg)==-1)