UNIX环境高级编程学习之第十五章进程间通信 – 信号量的使用(信号灯的使用, 计算信号灯)
[code lang=”cpp”]/* User:Lixiujie
* Date:20100829
* Desc:信号量的使用(信号灯的使用, 计算信号灯)
* File:semaphore.c
* System:Ubuntu 64bit
* gcc semaphore.c -o SemDemo
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
unsigned short *array; /* array for GETALL & SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */ //test!!
void *__pad;
};

/* 取当前文件路径 */
char* getCurrentFilePath(char *szCurrentFilePath){
char szBuf[256] = { 0x00 };
strcpy(szBuf, __FILE__);
if (strstr(szBuf, "/") == NULL){
memset(szBuf, 0x00, sizeof(szBuf));
strcpy(szBuf, getenv("PWD"));
strcat(szBuf, "/");
strcat(szBuf, __FILE__);
}
strcpy(szCurrentFilePath, szBuf);
return szCurrentFilePath;
}
int main(int argc, char * argv[]){
char szFilePath[256] = { ‘/0’ };
key_t semKey;
int i;
union semun arg;
int semID;
int tmpErrno;
/* 等待信号集初始化完成尝试次数 */
int iMaxTries = 3;
/* 信号集初始化完成标志 */
int iInitOk = 0;
/* 当前信号集信息, 内核分配给每个信号集的结构 */
struct semid_ds semCurrInfo;
/* 系统信号集限制信息 */
struct seminfo semInfo;
struct sembuf semBuf;
getCurrentFilePath(szFilePath);
/* 产生key */
semKey = ftok(szFilePath, 1);
if (-1 == semKey){
perror("main() ftok() is failed!/n");
exit(1);
}
/* 创建一个信号量集,只包含一个信号 */
semID = semget(semKey, 1, IPC_CREAT|IPC_EXCL|00666);
if (-1 == semID){
tmpErrno = errno;
if (EEXIST == tmpErrno){
perror("main() semget() is already exists!/n");
/* 获取一个信号量集,只包含一个信号 */
semID = semget(semKey, 1, IPC_CREAT|00666);
if (-1 == semID){
perror("main() semget() semget() is failed!/n");
exit(1);
}
arg.buf = &semCurrInfo;
for (i = 0;i < iMaxTries;i++){
if (semctl(semID, 0, IPC_STAT, arg) == -1){
perror("main() semget() semget() is failed!/n");
}else{
/* sem_otime:最后semop修改时间,创建初始值为0 */
if (arg.buf->sem_otime != 0){
iInitOk = 1;
break;
}
}
sleep(1);
}
if (0 == iInitOk){
/* 第一个创建semaphore进程没有初始化完成或刚好初始化完成,
* 本次要初始化一下,否则无法下面的工作。
*/
arg.val = 1;/* 资源数 */
if (semctl(semID, 0, SETVAL, arg) == -1){
perror("main() semget() semctl() is failed/n");
exit(-1);
}
}
} else {
perror("main() semget() is failed!/n");
exit(1);
}

}else{
arg.val = 1;/* 资源数 */
if (semctl(semID, 0, SETVAL, arg) == -1){
perror("main() semctl() is failed/n");
exit(-1);
}
}
/* 打印当前信号集信息 */
arg.buf = &semCurrInfo;
if (semctl(semID, 0, IPC_STAT, arg) == -1){
perror("main() semctl() is failed/n");
exit(-1);
}
printf("当前拥有用户:%d/n", arg.buf->sem_perm.uid);
printf("当前拥有用户组:%d/n", arg.buf->sem_perm.gid);
printf("创建用户:%d/n", arg.buf->sem_perm.cuid);
printf("创建用户组:%d/n", arg.buf->sem_perm.cgid);
/* 打印当前系统信号集限制信息 */
arg.__buf = &semInfo;
if (semctl(semID, 0, SEM_INFO, arg) == -1){
perror("main() semctl() is failed/n");
exit(-1);
}
printf("the number of entries in semaphore map is %d /n", arg.__buf->semmap);
printf("max number of semaphore identifiers is %d /n", arg.__buf->semmni);
printf("mas number of semaphores in system is %d /n", arg.__buf->semmns);
printf("the number of undo structures system wide is %d /n", arg.__buf->semmnu);
printf("max number of semaphores per semid is %d /n", arg.__buf->semmsl);
printf("max number of ops per semop call is %d /n", arg.__buf->semopm);
printf("max number of undo entries per process is %d /n", arg.__buf->semume);
printf("the sizeof of struct sem_undo is %d /n", arg.__buf->semusz);
printf("the maximum semaphore value is %d /n", arg.__buf->semvmx);
/* 申请使用资源 */
printf("ask for resource start./n");
semBuf.sem_num = 0;
semBuf.sem_op = -1;
semBuf.sem_flg = SEM_UNDO; /* 异常退出资源回收 */
if (semop(semID, &semBuf, 1) == -1){
perror("main() semop() op -1 is failed!/n");
exit(1);
}
printf("ask for resource complete./n");

sleep(10);

/* 释放资源 */
printf("free resource start./n");
semBuf.sem_num = 0;
semBuf.sem_op = 1;
semBuf.sem_flg = SEM_UNDO; /* 异常退出资源回收 */
if (semop(semID, &semBuf, 1) == -1){
perror("main() semop() op 1 is failed!/n");
exit(1);
}
printf("free resource complete./n");

/* 显示的删除信号集 */
if (semctl(semID, 0, IPC_RMID) == -1){
perror("main() semctl() IPC_RMID is failed!/n");
}else{
printf("Remove semaphore OK!/n");
}
return 0;
}

[/code]

发表评论