如何在Go中使用POSIX信号量


go本身提供的 semaphore只能在同一个进程多个协程或线程间使用,无法在不同的 go进程之间使用,所以本文介绍,如何使用 go中的 syscall来使用 POSIX系统提供的 命名信号量

本文涉及到的代码可在此仓库查看:semaphore

Go 中的系统调用

go中,系统调用是通过syscall包提供的Syscall函数来进行系统调用的,不同的系统调用有不同的trap,以及不同长度的参数

trap

gosyscall包中定义了大量的系统调用码,具体定义在文件1.20.6/go/src/syscall/zsysnum_darwin_arm64.go。不同操作系统上,定义所使用的文件是不同的,这些定义都是通过不同系统的c 语言头文件自动生成的。比如linux amd64操作系统的定义在1.20.6/go/src/syscall/zerrors_linux_amd64.go

不同长度的参数

syscall包有Syscall、Syscall6两个函数,对应于不同的操作系统调用参数长度的情况。

Syscall总共接收4个参数,第一个是trap定义,描述具体的系统调用,剩下的3个是系统调用所需的参数。

Syscall6总共接收7个参数,第一个是trap定义,描述具体的系统调用,剩下的6个是系统调用所需的参数。

如果使用SyscallSyscall6时,系统调用所需的参数不满足函数形参所需的数量,则剩下的参数传0

例如,在POSIX系统上打开一个命名信号量的系统调用是:

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

因为系统调用的参数有4个,而Syscall接收的全部形参才4个,所以Syscall不能满足我们的需求,只能使用Syscall6这个函数。而Syscall6总共需要7个形参,其中有6个是系统调用参数,我们只有4个系统调用参数,那么剩下的2个系统调用参数,我们就可以使用0替代,例如:

r1, r2, err := syscall.Syscall6(
  syscall.SYS_SEM_OPEN,
	uintptr(unsafe.Pointer(cs)),  // name
	uintptr(C.O_CREAT),  // flag
	uintptr(mode),  // mode
	uintptr(value),  // value
	0,  // 没有更多参数,使用 0
	0,
)

实现Samephore

信号量的操作主要有这么几个系统调用:sem_open、sem_wait、sem_trywait、sem_post、sem_close、sem_unlink

在具体实现之前,我们先引入C头文件和定义一些结构,方便我们后续使用。

我们可以创建一个 semaphore/semaphore.go的包ÿ

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值