#include<unistd.h>#include<stdlib.h>#include<stdio.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>
#ifndef _SEMUN_H //条件编译,即若SEMUN在头文件中没有被定义,就进行下面的编译#define _SEMUN_Hunion semun{ int val; //设置semnum指定的信号量的值 struct semid_ds *buf; unsigned short int *array; struct seminfo *_buf;};#endif
static int set_semvalue(void);static void del_semvalue(void);static int semaphore_p(void);static int semaphore_v(void);
static int sem_id;
int main(int argc,char *argv[]){ int i; int pause_time; char *op_in="First in/n"; char *op_out="First out/n";
srand((unsigned int)getpid()); //以getpid()为随机序列的种子 sem_id=semget((key_t)1234,1,0666|IPC_CREAT); /*为一个新创建的集合返回标识符, 或者返回具有相同键值的已存在信号集的标识符*/
if(argc>1){ if(!set_semvalue()){ //信号初始化失败 fprintf(stderr,"Failed to initialize semaphore/n"); } op_in="Second in/n"; op_out="Second out/n"; sleep(2); } for(i=0;i<5;i++){ if(!semaphore_p()) exit(EXIT_FAILURE); printf("%s",op_in); fflush(stdout); pause_time=rand()%3; sleep(pause_time); printf("%s",op_out); fflush(stdout); if(!semaphore_v()) exit(EXIT_FAILURE); pause_time=rand()%2; sleep(pause_time); } printf("/n%d-finished/n",getpid()); if(argc>1){ sleep(10); del_semvalue(); } exit(EXIT_SUCCESS);}
static int set_semvalue(void){ union semun sem_union;
sem_union.val=1; if(semctl(sem_id,0,SETVAL,sem_union)==-1) /* 根据sem_union.val设置semmun指定的信号量的值, 错误返回-1,成功返回正数 */ return(1); //前面条件成立,即返回-1,则返回调用函数中的值为1}
static void del_semvalue(void){ union semun sem_union; if(semctl(sem_id,0,IPC_RMID,sem_union)==-1) /* 从系统中删除标识符为sem_id的信号集, 错误返回-1,正确返回正数 */ fprintf(stderr,"Failed to delete semaphore/n");}
static int semaphore_p(void){ struct sembuf sem_b; //sembuf结构在Linux/sem.h中有定义 sem_b.sem_num=0; //信号在数组中的索引 sem_b.sem_op=-1; /* 这里为负数,相当于P操作,从信号量中减去sem_op的绝对值(1) */ sem_b.sem_flg=SEM_UNDO; /*操作标志为SEM_UNDO,当一个进程改变了信号量的值进入临界区后, 但因为其他原因没有退出临界区的情况下,会造成信号量永远不能释放, 此时,系统用SEM_UNDO实施还原操作,信号量还原为进程操作前的状态 */ if(semop(sem_id,&sem_b,1)==-1){ //P操作发生错误,返回-1,条件成立;否则条件不成立 fprintf(stderr,"semaphore_p failed"); return(0); //上面的条件成立,即发生错误,返回0给调用函数 }} //luojiazhen corrected it 05年12月20日
static int semaphore_v(void){ struct sembuf sem_b;
sem_b.sem_num=0; sem_b.sem_op=1; /* 这里为正数,相当于V操作,在信号量中增加sem_op的值(1), 这意味着该进程从临界区返回,释放临界资源 */ sem_b.sem_flg=SEM_UNDO; if(semop(sem_id,&sem_b,1)==-1){ //V操作发生错误,返回-1,条件成立;否则条件不成立 fprintf(stderr,"semaphore_v failed"); return(0); } return(1);}
