fishonesea

android 驱动,移植,qq群:91386163 推荐《Android深度探索(卷1):HAL与驱动开发》
  博客园  :: 首页  :: 新随笔  :: 管理

linux app 层信号量使用

Posted on 2012-02-15 20:05  fishonesea  阅读(625)  评论(0编辑  收藏  举报
以下转自:
http://hi.baidu.com/andio/blog/item/07bb5ec270e3bb26e4dd3be4.html

俩种方法,一是sem_open,一是semget
原理哥就不说了,百度一下,sem_open,网络上一大堆,直接上代码,是正经
免责声明:
1、 此代码为个人基于学习目的所写,如果有人运行次代码造成了不可预料的后果,比如硬盘损坏,原子弹爆炸等
本人概不负责!!
PS:
BS一切照抄别人不用自己大脑想问题的人!
BS一切只说原理不上代码的光说不练的人!
代码分为3部分sem_sync.h a.c b.c
此文姐妹片:利用semget方法 http://hi.baidu.com/andio/blog/item/3d6096d61223a03c06088b3f.html
1. sem_sync.h

#ifndef _SEM_SYNC_H_

#define _SEM_SYNC_H_
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

char SEM_A_TASK_IS_FREE[]= "a_task_is_free";
char SEM_B_TASK_IS_FREE[]= "b_task_is_free";

#endif
2 进程a
#include "sem_sync.h"
int main()
{
sem_t *sem_a_task_is_free;
sem_t *sem_b_task_is_free;
sem_a_task_is_free = sem_open(SEM_A_TASK_IS_FREE,O_CREAT,0644,1);
sem_b_task_is_free=sem_open(SEM_B_TASK_IS_FREE,O_CREAT,0644,0);
if(sem_a_task_is_free == SEM_FAILED||sem_b_task_is_free == SEM_FAILED)
{
perror("unable to create semaphore");
sem_unlink(SEM_A_TASK_IS_FREE);
exit(-1);
}

while(1==1)
{
printf("run a task......\n");
getchar();

sem_post(sem_a_task_is_free);
printf("send->a_task_is_free\n");

printf("\nwaite sem_b_task_is_free\n");
sem_wait(sem_b_task_is_free);
printf("recv<-sem_b_task_is_free\n");
}

sem_close(sem_a_task_is_free);
sem_unlink(SEM_A_TASK_IS_FREE);
_exit(0);
}
//gcc a.c -lpthread -o a

3 进程b
#include "sem_sync.h"

int main()
{
sem_t *sem_a_task_is_free;
sem_t *sem_b_task_is_free;
sem_a_task_is_free = sem_open(SEM_A_TASK_IS_FREE,O_CREAT,0644,0);
sem_b_task_is_free=sem_open(SEM_B_TASK_IS_FREE,O_CREAT,0644,1);
if(sem_a_task_is_free == SEM_FAILED||sem_b_task_is_free == SEM_FAILED){
perror("unable to create semaphore");
sem_unlink(SEM_B_TASK_IS_FREE);

exit(-1);
}

while(1==1){
printf("\nrun b_task......\n");
sleep(1);

sem_post(sem_b_task_is_free);
printf("send->sem_b_task_is_free\n");

printf("\nwaite a_task_is_free\n");
sem_wait(sem_a_task_is_free);
printf("recv<-a_task_is_free\n");
}
sem_close(sem_a_task_is_free);
sem_close(sem_b_task_is_free);

sem_unlink(SEM_B_TASK_IS_FREE);
exit(0);
}
//gcc b.c -lpthread -o b

#./a
#./b
原理哥就不说了,百度一下,semget,网络上一大堆,直接上代码,是正经
免责声明:
1、 此代码为个人基于学习目的所写,如果有人运行次代码造成了不可预料的后果,比如硬盘损坏,原子弹爆炸等
本人概不负责!!
2、如果转载请标注出处!
http://hi.baidu.com/andio/blog/item/3d6096d61223a03c06088b3f.html
PS:

BS一切照抄别人不用自己大脑想问题的人!
BS一切只说原理不上代码的光说不练的人!
代码分为4部分usr_sem.h a.c b.c Makefile。
此文姐妹篇:利用sem_open方法,http://hi.baidu.com/andio/blog/item/07bb5ec270e3bb26e4dd3be4.html
1. usr_sem.h

#ifndef _usr_sem_h_
#define _usr_sem_h_
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
/*
利用ftok函数实现 关键key
*/

#define SEM_KEY ftok("/",12)

union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
/*
声明共用信号量集合
*/

struct sembuf p_start_a_task= {0,-1,SEM_UNDO},
p_start_b_task = {1,-1,SEM_UNDO},
v_a_task_is_end= {1,1,SEM_UNDO},
v_b_task_is_end = {0,1,SEM_UNDO};

/*
SEM_CREAT(semid)
这个 宏 的主要功能是创建信号量,并将其标识符
赋给semid
usr_sem_creat(semid) 调用了该宏
*/

#define SEM_CREAT(semid) \
if((semid = semget(SEM_KEY,2,0600 | IPC_CREAT | IPC_EXCL))<0)\
{\
if(errno==EEXIST)\
{\
semid = semget(SEM_KEY,2,0600 | IPC_CREAT);\
if(semid<0)\
printf("semget error");\
}\
}
#define usr_sem_creat(semid)\
SEM_CREAT(semid)

/*
SEM_SETVALUE(SEM_ID,SEM_INDEX,SEMUN,VALUE)\
这个 宏 的主要功能是给信号量赋值,
@SEM_ID:标识符
@SEM_INDEX:索引
@SEMUN:联合体,
@VALUE:值
usr_sem_set_value(SEM_ID,SEM_INDEX,SEMUN,VALUE) 调用了该宏
*/

#define SEM_SETVALUE(SEM_ID,SEM_INDEX,SEMUN,VALUE)\
SEMUN.val = VALUE;\
if(semctl(SEM_ID,SEM_INDEX,SETVAL,SEMUN)<0)\
printf("semctl sem %d error",SEM_INDEX);

#define usr_sem_set_value(SEM_ID,SEM_INDEX,SEMUN,VALUE) \
SEM_SETVALUE(SEM_ID,SEM_INDEX,SEMUN,VALUE)

/*
usr_sem_wait(SEM_ID,P)
usr_sem_post(SEM_ID,V)
模拟sem_wait,sem_post函数
@SEM_ID:标识符
@P:P类型信号量
@V:V类型信号量,
@VALUE:值
usr_sem_set_value(SEM_ID,SEM_INDEX,SEMUN,VALUE) 调用了该宏
*/

#define usr_sem_wait(SEM_ID,P)\
semop(SEM_ID,&P,1);

#define usr_sem_post(SEM_ID,V)\
semop(SEM_ID,&V,1);
#endif
2. a.c
#include "usr_sem.h"
/*
此代码断的主要功能是模拟a进程
*/

int main()
{

/*变量声明*/
int semid;
union semun arg;
/*宏操作实现信号量创建和赋值等*/

usr_sem_creat(semid);
usr_sem_set_value(semid,0,arg,1);
usr_sem_set_value(semid,1,arg,0);
printf("\n**********U can press enter key to continue this task!**************\n");
/*
while(1)模拟定时任务结构
程序结构
while(1)
{
usr_sem_wait(semid,p_start_a_task);
<s>//访问临界区域的 代码
usr_sem_post(semid,v_a_task_is_end);
}
*/

while(1)
{
printf("\n <===is rcving p_start_a_task.......\n");
usr_sem_wait(semid,p_start_a_task);
printf("rcv p_start_a_task.......[OK]\nin %s,running a_task[%d]......\n",__FILE__,random());
getchar();
printf("finish a_task,now is snding v_a_task_is_end..... \n");

usr_sem_post(semid,v_a_task_is_end);
printf(" ===>snd v_a_task_is_end.......[OK]\n");
}
}
3. b.c
#include "usr_sem.h"
/*
此代码断的主要功能是模拟b进程
*/

int main()
{
int semid;

union semun arg;
/*
宏操作实现信号量创建和赋值等
*/

usr_sem_creat(semid);
usr_sem_set_value(semid,0,arg,1);
usr_sem_set_value(semid,1,arg,0);

/*
程序结构
while(1)
{
usr_sem_wait(semid,p_start_b_task);
<s>//访问临界区域的 代码
usr_sem_post(semid,v_b_task_is_end);

}
*/

while(1){
printf("\n <===is rcving p_start_b_task.......\n");
usr_sem_wait(semid,p_start_b_task);
printf("rcv p_start_b_task.......[OK]\nin %s,running b_task[%d]......\n",__FILE__,random());

printf("finish b_task,now is snding v_b_task_is_end..... \n");
usr_sem_post(semid,v_b_task_is_end);
printf(" ===>snd v_b_task_is_end.......[OK]\n");
}
}

4. Makefile
#makefil
#CROSS_COMPILE = /opt/EmbedSky/4.3.3/bin/arm-linux-
CROSS_COMPILE =
CC = $(CROSS_COMPILE)gcc
LNK = $(CROSS_COMPILE)ld
AR = $(CROSS_COMPILE)ar

CFLAG=-o
all:
t$(CC) $(CFLAG) a a.c
t$(CC) $(CFLAG) b b.c
clean:
trm -f *.o