linux/unix信号量的值

来源:互联网 发布:淘宝产品摄影布光 编辑:程序博客网 时间:2024/06/07 16:32

或许有许多程序员对linux信号量的用法,信号令的值究竟如何计算,用户如何获得?本篇文章江告诉你如何获得让你迷惑的信号的值!



#include<stdio.h>

#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/shm.h>
#include<errno.h>
#include<string.h>
#include<signal.h>


#if defined(_GNU_LIBRARY_)&& 
!defined(_SEM_SEMUN_UNDEFINED)
#else


union semun //头文件中没有,应用程序自己定义
{
int val; //value for SETVAL :用于设置semid所标识的
//信号量集中第semnum个信号量的值
struct semid_ds *buf;//buffer for IPC_STAT,IPC_SET
//用于用户获取或者填充semid所标识的信号
//量集的缓冲区
unsigned short int *array;//array for GETALL,SETALL
//用于用户获取或填充semid 所标识的信号
//量集中信号量的个数
struct seminfo *_buf;//buffer for IPC_INFO(linux-specific)
};


#endif
#define SHMDATASIZE 1000 //共享内存的大小
#define BUFFERSIZE (SHMDATASIZE-sizeof(int))//缓冲区的大小
#define SN_EMPTY 0
#define SN_FULL 1


int delsemid=0;
int emptem=0;
int fultem=0;
void server(void);
void client(int shmid);
void del(void);
void sigdel(int signum);
void locksem(int semid,int semnu);
void unlocksem(int semid,int semnu);
void cliwrite(int shmid,int semid,char *buff);


int main(int argc,char **argv)
{


if(argc<2)
server();
else
client(atoi(argv[1]));
/*
首先运行server 根据显示的shmid
以shmid为参数,运行client程序
atoi(argv[1]) 将char型的字符串转换为int
*/
return 0;
}


void server(void)
{
union semun sunion;//semctl函数使用
int semid,shmid;//声明信号量和共享内存标识符
void *shmdata;
char *buff;
/*
创建一个信号量集包含两个信号量
用于阻塞读写进程
*/


//int semget(key_t key,int nsems,int semflg);
//成功返回信号量集的引用标识符
semid=semget(IPC_PRIVATE,2,SHM_R | SHM_W);


delsemid=semid;//暂时保存信号量集合标识符


//删除信号量
atexit(&del);
signal(SIGINT,&sigdel);




sunion.val=1;//信号量可用
//int semctl (int semid,int semnum,int cmd,union semun arg)
//由semnum制定对特定的信号量进行cmd
//操作
semctl(semid,SN_EMPTY,SETVAL,sunion);
//将semid所标识的信号量集中的
//第0个信号量的值设置为1
printf("the first semaphore'value is %d\n",SETVAL);


sunion.val=0;//信号量不可用
semctl(semid,SN_FULL,SETVAL,sunion);
//将semid所标识的信号量集中的
//第1个信号量的值设置为0


printf("the second semaphore'value is %d\n",SETVAL);
emptem=semctl(semid,SN_EMPTY,GETVAL,sunion);
fultem=semctl(semid,SN_FULL,GETVAL,sunion);
printf("3*************************************3\n")
printf("the firet semaphore value is %d\n",emptem);
printf("the second semaphore value is %d\n",fultem);
printf("######################################\n");








//创建共享内存
//int (key_t key,int size,int flag)
//size --共享内存的大小 flag调用函数
//的操作类型,设置共享内存的访问权限
//成功返回共享内存标识符失败返回-1


shmid=shmget(IPC_PRIVATE,SHMDATASIZE,IPC_CREAT |SHM_W |SHM_R);
printf("The shmid is %d\n",shmid);
//shadow the memory
//void *shmat (int shmid,void *addr,int flag);
//shmid 是要附加的共享内存段标识符
//将addr和flag全部设置为0
//系统自动查找进程地址空间将共享内存
//附加到第一块有效的内存区上此时flag无效
shmdata=shmat(shmid,0,0);//
//由shmdata保存共享内存区域的指针
//调用失败返回-1
printf("The shared memory beginning at %x\n",shmdata);
//删除共享内存
//int shmctl(int shmid,int cmd,shmid_ds *buf)
shmctl(shmid,IPC_RMID,NULL);


*(int *)shmdata=semid;
//shmdata 是共享内存的首地址
//将信号量存放如共享内存中
buff=shmdata+sizeof(int);
//共享内存的前四个字节被semid所占有
//buff指向共享内存shmdata首地址+semid所占的4
//字节的下一个字节
printf("server is running with id %d\n",shmid);
while(1)
{
printf("waiting until full....");
fflush(stdout);//强制输出到屏幕上
//不必等待缓冲区满
//在使用信号令锁定 共享内存之前
//查看所有信号量的值
emptem=semctl(semid,SN_EMPTY,GETVAL,sunion);
fultem=semctl(semid,SN_FULL,GETVAL,sunion);


printf("######################################\n")
printf("the firet semaphore value is %d\n",emptem);
printf("the second semaphore value is %d\n",fultem);
printf("######################################\n");


locksem(semid,SN_FULL);
emptem=semctl(semid,SN_EMPTY,GETVAL,sunion);
fultem=semctl(semid,SN_FULL,GETVAL,sunion);




printf("1**************************************1\n")
printf("the firet semaphore value is %d\n",emptem);
printf("the second semaphore value is %d\n",fultem);
printf("######################################\n");


printf("done\n");
printf("memssage received:%s\n",buff);
unlocksem(semid,SN_EMPTY);


emptem=semctl(semid,SN_EMPTY,GETVAL,sunion);
fultem=semctl(semid,SN_FULL,GETVAL,sunion);


printf("2*************************************2\n")
printf("the firet semaphore value is %d\n",emptem);
printf("the second semaphore value is %d\n",fultem);
printf("######################################\n");


}
}


void client(int shmid)
{
int semid;
char *buff;
void *shmdata;
shmdata=shmat(shmid,0,0);
semid=*(int *)shmdata;
buff=shmdata+sizeof(int);
printf("clinet operational:shm id is %d\n",shmid);
while(1)
{
char input[3];
printf("\n\nmenu\n1.send a message\n");
printf("2.exit\n");
fgets(input,sizeof(input),stdin);
switch(input[0])
{
case '1':cliwrite(shmid,semid,buff);break;
case '2':exit(0);break;
}
}


}


//在程序退出时执行的操作
void del(void)
{
printf("master exiting :deleting semphore.\n");
//删除信号量集合中第0个信号量
//delsemid 保存了信号量集引用标识符semid
if(semctl(delsemid,0,IPC_RMID,0)==-1)
printf("error releasing semaphore.\n");
}


void sigdel(int signu)
{
exit(0);
}


void locksem(int semid,int semnu) //共享内存段加锁
{
/*
struct sembuf 
{
ushort sem_num;//指定要操作的信号量
short sem_op;//进行如何操作
short sem_flag; 与次函数相关的有IPC_NOWAIT /
SEM_UNDO
}
*/
struct sembuf sb;
sb.sem_num=semnu;
sb.sem_op=-1;//进程希望使用资源
printf("***********************************\n");
//打印出信号量集中第一个信号量的值
//最后一次访问资源的进程ID  、等待可以利用资源
//的进程数和等待独占资源给信号量加锁的进程数
printf("semid.sem_base.semval is %d\n",semid.sem_base.semval);
printf("semid.sem_base.sempid is %d \n"semid.sem_base.sempid);
printf("semid.sem_base.semncnt is %u\n",semid.sem_base.semncnt);
printf("semid.sem_base.semzcnt is %u\n"semid.sem_base.semzcnt);
printf("sb.sem_op is %d\n",sb.sem_op);
sb.sem_flg=SEM_UNDO;
//用printf打印出SEM_UND宏定义的值
printf("%d",sb.sem_flg);


//int semop(int semid,struct sembuf semoparry[],unsigned nsops)
//信号量操作函数 sb是一个sembuf结构数组
//制定semop函数的操做,nsop是数组元素
semop(semid,&sb,1);
/*由于进程希望分配资源sb.sem_op <0
同时设置sem_flga=SEM_UNDO所以比较semid.sem_base.semval
和sb.sem_op绝对值的大小。如果sem_base.semval大于
等于sem_op的绝对值,说明资源足够分
配给此进程,则sem_base.semval减去sem_op的绝对值。
若此时设置了SEM_UNDO位 , 则 信 号 量 的 调 整 值 
将 加 上sem_op的 绝 对 值 。 如 果
sem_base.semval小 于sem_op的 绝 对 值 , 表 示 资 源 不 足 ?
若 设 置 了
IPC_NOWAIT位 , 则 函 数 出 错 返 回 ,
否 则semid_ds结 构 中 的sem_base.semncnt加1, 进 程 等 待 直 至
sem_base.semval大 于 等 于sem_op的绝对值
*/
printf("semid.sem_base.semval is %d\n",semid.sem_base.semval);
}






void unlocksem(int semid,int semnu)
{
struct sembuf sb;
sb.sem_num=semnu;
sb.sem_op=1;
sb.sem_flg=SEM_UNDO;
semop(semid,&sb,1);
}


void cliwrite(int shmid,int semid,char *buff)
{printf("waiting until empty....");
fflush(stdout);
locksem(semid,SN_EMPTY); //申请使用信号量
printf("done\n");
printf("enter message:");
fgets(buff,BUFFERSIZE,stdin);
unlocksem(semid,SN_FULL);
}





原创粉丝点击