信号量学习笔记

对于linux的程序员来说,信号量是一个不能回避的问题。下面我简要地介绍下信号量在不同状态下的使用。

一,内核态

l         就是写驱动程序时遇到的信号量。

1.       定义信号量

struct semaphore sem;

2.       初始化信号量

void sema_init(struct semaphore *sem,int val);

       val是被初始化的信号量的值,一般初始化为0或1。

void init_MUTEX(struct semaphore *sem)等价于sema_init(struct semaphore *sem,1)

void init_MUTEX_LOCKED(struct semaphore *sem)

等价于sema_init(struct semaphore *sem,0)

3.       定义和初始化两项可以合并

DECLEAR_MUTEX(name)           DECLEAR_MUTEX_LOCKED(name)

4.       获得信号量

void down(struct semaphore *sem);

int down_interruptible(struct semaphore *sem);

int down_trylock(struct semaphore *sem);

5.       释放信号量

void up(struct semaphore *sem);

 

l         Linux提供了一种比信号量更好的同步机制,完成量

1.定义    struct completion my_completion;

2.初始化 init_completion(&my_completion)

3.定义和初始化 DECLEAR_COMPLETION(my_completion)

4.等待完成量 void wait_for_completion(struct completion *c);

5.唤醒完成量 void complete(struct completion *c);

                     void complete_all(struct completion *c);

 

l         互斥量

定义和初始化

struct mutex my_tex;

mutex_init(&my_tex);

获取互斥量

void fastcall mutex_lock(struct mutex *lock);

int fastcall mutex_lock_interruptible(struct mutex *lock);

int fastcall mutex_trylock(struct mutex *lock);

释放互斥量

void fastcall mutex_unlock(struct mutex *lock);

二,用户态——线程信号量

l         源于POSIX的扩展,信号量函数的名字都以sem_开头。

1.创建并初始化函数

       int sem_init(sem_t *sem,int pshared,unsigned int value)

       和内核态的信号初始化函数太像了^-^,pshared,一般初始化为0

       2.等待信号量

       int sem_wait(sem_t *sem)

       3.唤醒信号量

       int sem_post(sem_t *sem)

       4.清理信号量

       int sem_destroy(sem_t *sem)

l         互斥量

       相关函数

int pthread_mutex_init(pthread_mutex *mutex,const pthread_mutexattr_t *mutexattr);

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_destroy(pthread_mutex_t *mutex);

 

三,进程间通信的信号量

该组信号量接口函数源于System V。

这一组接口比前面介绍的使用起来稍复杂一点。

n         定义并获得信号标志符函数

int semget(key_t key,int num_sems,int sem_flags)

信号没有名称,但是有一个semget返回的信号id,用来标志信号。key,可以任意指定。num_sems是需要的信号量的数目,通常为1。sem_flags,由信号量的权限和一些特定意义的宏按位或组成。

例如:sem_id=semget((key_t)1234, 1, 0666 | IPC_CREAT);

n         信号量值行为函数

int semop(int sem_id,struct sembuf *sem_ops,size_t num_sem_ops)

sem_id,是semget调用的返回值

struct sembuf{short sem_num;short sem_op;short sem_flg;}。sem_num,为信号量的编号,sem_op,可以是+1,或-1。+1,代表V操作,-!,代表P操作。flg,一般设置为SEM_UNDO,它的含义是如果这个进程在没有释放使用的信号量的情况下终止,操作系统会去处理释放工作。

num_sem_ops,有几个信号需要这样的操作处理。

例如:struct sembuf sem_b;

       sem_b.sem_num=0;

       sem_b.sem_op=-1;

       sem_b.sem_flg=SEM_UNDO;

if(semop(sem_id,&sem_b,1)==-1)

……

n         信号量值设置与处理函数

int semctl(int sem_id,int sem_num,int command,…)

sem_id,sem_num,与semop函数中的含义相同。

command,要采取的动作。

如果有第4个参数,那么就是

union semun{int val;struct semid_ds *buf;unsigned short *array;}

command有两个常用的命令SETVAL和IPC_RMID

SETVAL, 通过union semun中的val成员,设置sem_id代表的信号的初值

IPC_RMID, 删除不用的信号量标识符sem_id。

例:union semun sem_union;

sem_union.val=1;

semctl(sem_id,0,SETVAL,sem_union);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值