进程间通信之信号量semaphore--linux内核剖析( 八 )


示例程序调用semctl函数设置信号量的值程序#include #include #include #include #include //定义信号量操作共用体结构union semun{intval;struct semid_ds*buf;unsigned short*array;};int main(int argc,char *argv[]){int semid,nsems,i;struct semid_ds seminfo;unsigned short *ptr;union semun arg;if(argc < 2){printf("usage: semsetvalues [values ...]");exit(0);}//打开已经存在的信号量集合semid = semget(ftok(argv[1],0),0,0);arg.buf =//获取信号量集的相关信息semctl(semid,0,IPC_STAT,arg);nsems = arg.buf->sem_nsems;//信号量的个数if(argc != nsems + 2 ){printf("%s semaphores in set,%d values specified",nsems,argc-2);exit(0);}//分配信号量ptr = calloc(nsems,sizeof(unsigned short));arg.array = ptr;//初始化信号量的值for(i=0;i调用semctl获取信号量的值#include #include #include #include #include union semun{intval;struct semid_ds *buf;unsigned short*array;};int main(int argc,char *argv[]){intsemid,nsems,i;struct semid_ds seminfo;unsigned short *ptr;union semun arg;if(argc != 2){printf("usage: semgetvalues");exit(0);}//打开已经存在的信号量semid = semget(ftok(argv[1], 0), 0, 0);arg.buf =//获取信号量集的属性 , 返回semid_ds结构semctl(semid, 0, IPC_STAT, arg);nsems = arg.buf->sem_nsems;//信号量的数目ptr = calloc(nsems,sizeof(unsigned short));arg.array = ptr;//获取信号量的值semctl(semid, 0, GETALL, arg);for(i = 0; i < nsems; i++){printf("semval[%d] = %d\n", i, ptr[i]);}return EXIT_SUCCESS;}通过semctl实现PV操作的函数库#include #include #include #include union semun{intval;struct semid_ds*buf;unsigned short*array;};// 将信号量sem_id设置为init_valueint init_sem(int sem_id, int init_value){union semunsem_union;sem_union.val = init_value;if (semctl(sem_id, 0, SETVAL, sem_union) == -1){perror("Sem init");exit(1);}return 0;}// 删除sem_id信号量int del_sem(int sem_id){union semun sem_union;if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1){perror("Sem delete");exit(1);}return 0;}// 对sem_id执行p操作int sem_p(int sem_id){struct sembufsem_buf;sem_buf.sem_num = 0;//信号量编号sem_buf.sem_op= -1;//P操作sem_buf.sem_flg = SEM_UNDO;//系统退出前未释放信号量 , 系统自动释放if (semop(sem_id,exit(1);}return 0;}// 对sem_id执行V操作int sem_v(int sem_id){struct sembufsem_buf;sem_buf.sem_num = 0;sem_buf.sem_op= 1;//V操作sem_buf.sem_flg = SEM_UNDO;if (semop(sem_id,exit(1);}return 0;}#include #include #include #include static int nsems;static int semflg;static int semid;int errno=0;union semun {int val;struct semid_ds *buf;unsigned short *array;}arg;int main(){struct sembuf sops[2]; //要用到两个信号量 , 所以要定义两个操作数组int rslt;unsigned short argarray[80];arg.array = argarray;semid = semget(IPC_PRIVATE, 2, 0666);if(semid < 0 ){printf("semget failed. errno: %d\n", errno);exit(0);}//获取0th信号量的原始值rslt = semctl(semid, 0, GETVAL);printf("val = %d\n",rslt);//初始化0th信号量 , 然后再读取 , 检查初始化有没有成功arg.val = 1; // 同一时间只允许一个占有者semctl(semid, 0, SETVAL, arg);rslt = semctl(semid, 0, GETVAL);printf("val = %d\n",rslt);sops[0].sem_num = 0;sops[0].sem_op = -1;sops[0].sem_flg = 0;sops[1].sem_num = 1;sops[1].sem_op = 1;sops[1].sem_flg = 0;rslt=semop(semid, sops, 1); //申请0th信号量 , 尝试锁定if (rslt < 0 ){printf("semop failed. errno: %d\n", errno);exit(0);}//可以在这里对资源进行锁定sops[0].sem_op = 1;semop(semid, sops, 1); //释放0th信号量rslt = semctl(semid, 0, GETVAL);printf("val = %d\n",rslt);rslt=semctl(semid, 0, GETALL, arg);if (rslt < 0){printf("semctl failed. errno: %d\n", errno);exit(0);}printf("val1:%d val2: %d\n",(unsigned int)argarray[0],(unsigned int)argarray[1]);if(semctl(semid, 1, IPC_RMID) == -1){perror(“semctl failure while clearing reason”);}return(0);}信号量的牛刀小试——生产者与消费者问题1.问题描述: 有一个长度为N的缓冲池为生产者和消费者所共有 , 只要缓冲池未满 , 生产者便可将 消息送入缓冲池;只要缓冲池未空 , 消费者便可从缓冲池中取走一个消息 。 生产者往缓冲池 放信息的时候 , 消费者不可操作缓冲池 , 反之亦然 。
2.使用多线程和信号量解决该经典问题的互斥
#include #include #include #include #include #define BUFF_SIZE 10char buffer[BUFF_SIZE];char count;//缓冲池里的信息数目sem_t sem_mutex;//生产者和消费者的互斥锁sem_t p_sem_mutex;//空的时候 , 对消费者不可进sem_t c_sem_mutex;//满的时候 , 对生产者不可进void * Producer(){while(1){sem_wait(//当缓冲池未满时sem_wait(//等待缓冲池空闲count++;sem_post(if(count < BUFF_SIZE)//缓冲池未满{sem_post(}if(count > 0)//缓冲池不为空{sem_post(}}}void * Consumer(){while(1){sem_wait( //缓冲池未空时sem_wait(//等待缓冲池空闲count--;sem_post(if(count > 0){sem_post(}}return NULL;}int main(){pthread_t ptid,ctid;//initialize the semaphores//sem_init(//sem_init(//creating producer and consumer threadsif(pthread_create(exit(1);}if(pthread_create(exit(1);}if(pthread_join(ptid, NULL)) /* wait for the producer to finish */{printf("\n ERROR joining thread");exit(1);}if(pthread_join(ctid, NULL)) /* wait for consumer to finish */{printf("\n ERROR joining thread");exit(1);}//sem_destroy(//sem_destroy(//exit the main threadpthread_exit(NULL);return EXIT_SUCCESS;}