golang: fcntl文件锁

进程级强制锁,ubuntu的apt和dpkg进程使用此锁

1 锁结构

type Flock_t struct {
Type int16 //锁的类型: 读锁、写锁、解锁
Whence int16 //锁的范围 SEEK_SET, SEEK_CUR, SEEK_END 文件开头,当前位置,结尾。基准位置
Pad_cgo_0 [4]byte
Start int64 //相对于基准的偏移值。定义了锁的起始
Len int64 //锁字节即从偏移开始的连续字节数
Pid int32 //获取哪个进程处于阻塞(F_GETLK)
Pad_cgo_1 [4]byte
}

对于一个文件,flock加锁的范围是整个文件内容,而fcntl能对文件的任意部分加锁。

2 获取锁状态

package main
import (
"fmt"
"syscall"
)
func main() {
fd, err := syscall.Open("/var/lib/dpkg/lock-frontend", syscall.O_WRONLY, 0644)
if err != nil {
fmt.Println(err)
}
defer syscall.Close(fd)
// 声明一个锁结构体用于写入锁状态
fgetlk := syscall.Flock_t{}
/*
FcntlFlock(fd uintptr, cmd int, lk *Flock_t)
cmd: 使用F_GETLK获取锁状态并写入lk中
*/
err = syscall.FcntlFlock(uintptr(fd), syscall.F_GETLK, &fgetlk)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%#v\n", fgetlk)
/*
F_RDLCK = 0x0 读锁
F_WRLCK = 0x1 写锁
F_UNLCK = 0x2 解锁
*/
switch fgetlk.Type {
case syscall.F_WRLCK:
fmt.Println("write lock")
case syscall.F_RDLCK:
fmt.Println("read lock")
case syscall.F_UNLCK:
fmt.Println("unlock")
default:
}
}

3 加写锁

package main
import (
"fmt"
"io"
"os"
"syscall"
"time"
)
func main() {
fp := "/var/lib/dpkg/lock-frontend"
file, err := os.OpenFile(fp, os.O_WRONLY, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
fd := file.Fd()
flockt := syscall.Flock_t{
Type: syscall.F_WRLCK,
Whence: io.SeekStart,
}
/*
F_GETLK: 获取当前锁的状态
F_SETLK: 给当前文件上锁(非阻塞)
F_SETLKW: 给当前文件上阻塞锁(类似自旋锁)
读/写、写/写互斥, 读/读不互斥
*/
err = syscall.FcntlFlock(fd, syscall.F_SETLK, &flockt)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("加锁成功")
time.Sleep(time.Second * 15)
flockt.Type = syscall.F_UNLCK
syscall.FcntlFlock(fd, syscall.F_SETLK, &flockt)
fmt.Println("解锁成功")
// 这是其他进程即可获取锁
time.Sleep(time.Second * 15)
}

读锁

打开文件方法使用读方法打开os.Open() 或者os.OpenFile(fp, os.O_RDONLY, perm)

锁类型使用读锁, syscall.Flock_t

posted @   ishmaelwanglin  阅读(233)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示