Linux的进程编程-之二-进程间通信(信号灯-Semaphore)

1.1         Posix信号灯-Semaphore

信号灯有以下两种类型:

二值信号灯:信号灯的值只能取0或1。

计算信号灯:信号灯的值可以取任意非负值。

每个信号灯都对应一个struct sem结构:

struct sem

{

unsigned shortint      semval          // 信号灯值

pid_t                           sempid          // 上次对信号灯进行操作的进程id

unsigned shortint      semzcnt        // 等待信号灯值变为0的进程数目

unsigned shortint      semncnt        // 等待信号灯值变大的进程数目

}

1.1.1       信号灯的创建和删除

1.1.1.1     sem_open( )

#include<semaphore.h>

sem_t* sem_open( const char *name, int flag )

sem_t* sem_open( const char *name, int flag, mode_t mode, int value )

创建或获取named信号灯;成功返回信号灯的地址,失败返回SEM_FAILED((void*)-1)。

参数name指定与信号灯相关联的名字。

参数flag可以取O_CREAT、O_EXCL。

单独使用O_CREAT,如果不存在与name相关联的信号灯,就创建一个新的信号灯,并返回其地址,如果已经存在与name相关联的信号灯,就返回该信号灯的地址。

如果指定了O_CREAT,需要使用sem_open()的第二种形式,其中参数mode指定了新创建信号灯的访问权限,参数value指定了新创建信号灯的初始值。

单独使用O_EXCL是没有意义的,如果O_EXCL和O_CREAT一起使用,当与name相关联的信号灯已经存在时,就失败返回SEM_FAILED。

1.1.1.2     sem_init( )

#include<semaphore.h>

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

创建一个unnamed信号灯。

参数value:信号灯的初值;

参数pshared:是否多进程共享(非0)或只用于一个进程(0)。

成功返回0,失败返回-1。

1.1.1.3      sem_close( )

#include <semaphore.h>

int sem_close( sem_t *sem )

只是用来表明当前进程不再使用一个named信号灯,该信号灯可以被删除。

1.1.1.4     sem_unlink( )

#include<semaphore.h>

intsem_unlink( const char *name )

删除一个named信号灯,但是如果当前仍有其它进程正在使用该信号灯,则暂时放弃删除操作,并立即返回,直到其它进程通过调用sem_close( )关闭之后,再进行删除操作。

成功返回0,失败返回-1。

1.1.1.5     sem_destroy( )

#include<semaphore.h>

int sem_destroy( sem_t *sem )

删除一个unnamed信号灯。

成功返回0,失败返回-1。

1.1.2       信号灯的操作

1.1.2.1      sem_getvalue( )

#include<semaphore.h>

int sem_getvalue(sem_t * sem, int * sval)

读取信号灯的值,由sval返回。如果信号灯正处于locked状态,则sval返回0或者一个负值,其绝对值表明正在等待该信号灯的进程的数目。

成功返回0,失败返回-1。

1.1.2.2      sem_post( )

#include<semaphore.h>

int sem_post( sem_t * sem )

将信号灯的值加1。

成功返回0,失败返回-1。

1.1.2.3      sem_wait( )

#include<semaphore.h>

int sem_wait( sem_t * sem )

如果信号灯值>0,将信号灯值减1,成功返回。

如果信号灯值≤0,等待信号灯值>0,然后将信号灯值减1,成功返回。

成功返回0,失败返回-1。

1.1.2.4      sem_trywait( )

#include <semaphore.h>

int sem_trywait( sem_t * sem )

如果信号灯值>0,将信号灯值减1,成功返回。

如果信号灯值≤0,立即失败返回。

成功返回0,失败返回-1。

1.2         系统V信号灯-Semaphore

1.2.1       ftok( )

#include<sys/types.h>

#include<sys/ipc.h>

key_tftok( const char *name, int id )

参数name指定了文件名(包含路径),该文件必须存在,而且当前进程必须能够访问该文件。

参数id只有低8位有效。

只有当name和id取值都相同时,返回的键值key才是相同的。

成功返回键值,失败返回-1。

1.2.2       semget( )

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

intsemget( key_t key, int nsems, int semflg )

创建或获取信号灯集;成功返回与key相关联的信号灯集id,失败返回-1。

参数nsems指定创建或获取的信号灯集中包含信号灯的数目。

参数semflg可以取IPC_CREAT、IPC_EXCL、IPC_NOWAIT。

单独使用IPC_CREAT,如果不存在与键值key相关联的信号灯集,就创建一个新的信号灯集,并返回其id,如果已经存在与键值key相关联的信号灯集,就返回该信号灯集id。

单独使用IPC_EXCL是没有意义的,如果IPC_EXCL和IPC_CREAT一起使用,当与键值key相关联的信号灯集已经存在时,就失败返回-1。

下面两种情况会创建一个新的信号灯集:

1.参数semflg指定IPC_CREAT,而且没有信号灯集与键值key相关联;

2.参数key指定IPC_PRIVATE;

参数semflg的低9位指定新创建信号灯集的访问权限:

所有者

组成员

其他成员

执行

执行

执行

         

1.2.3       semop( )

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

intsemop( int semid, struct sembuf * sops, unsigned nsops )

#include<time.h>

intsemtimedop( int semid, struct sembuf *sops, unsigned nsops, struct timespec*timeout )

参数sops指定了一组操作,用一个数组表示。

参数nsops指定了操作的数目,也就是数组的大小。

struct sembuf

{

unsigned short     sem_num;            /*semaphore index in array,0对应第一个信号灯*/

short                    sem_op;               /*semaphore operation */

short                    sem_flg;                     /* operation flags */

};

sem_flg可取:IPC_NOWAIT或SEM_UNDO(进程结束时,对信号灯集进行undo操作)。

sem_op指定了三种操作:

1.如果sem_op>0,信号灯值加上sem_op,成功返回。

2.如果sem_op = 0:

1.信号灯值为0,成功返回;

2.信号灯值不为0而且sem_flg设置了IPC_NOWAIT,失败返回;

3.信号灯值不为0而且sem_flg未设置IPC_NOWAIT,挂起当前进程直到发生:

1.信号灯值变为0,成功返回;

2.信号灯所在的信号灯集被删除,失败返回;

3.等待超时,失败返回。

3.如果sem_op<0:

1.信号灯值≥abs(sem_op),信号灯值减去abs(sem_op),成功返回;

2.信号灯值<abs(sem_op)而且sem_flg设置了IPC_NOWAIT,失败返回;

3.信号灯值<abs(sem_op)而且sem_flg未设置IPC_NOWAIT,挂起当前进程直到发生:

1.信号灯值≥abs(sem_op),信号灯值减去abs(sem_op),成功返回;

2.信号灯所在的信号灯集被删除,失败返回;

3.等待超时,失败返回。

注意:Linux保证所有操作的原子性,也就是说要么完成所有操作成功返回,要么什么操作都不做失败返回。成功返回0,失败返回-1。

1.2.4       semctl( )

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

intsemctl( int semid, int semnum, int cmd/, union semun arg / )

获取或设置信号灯集的属性,参数semid指定信号灯集,参数semnum指定信号灯。

参数arg用于设置或返回信号灯集的信息,只对某些cmd操作有意义。

union semun

{

int   val;

struct semid_ds   * buf;

unsigned short     * array;

};

参数cmd指定具体的操作类型;

IPC_RMID        删除信号灯集

IPC_STAT          获取信号灯集的信息,由arg.buf返回

IPC_SET            设置信号灯集的信息,由arg.buf设置

GETALL            获取所有信号灯的值,由arg.array返回

SETALL            设置所有信号灯的值,由arg.array设置

SETVAL            设置semnum信号灯的值,由arg.val设置

GETVAL           返回semnum信号灯的值

GETPID             返回semnum信号灯的sempid

GETNCNT        返回semnum信号灯的semncnt

GETZCNT         返回semnum信号灯的semzcnt

成功返回0或对应值,失败返回-1。

 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值