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 @ 2023-12-04 17:02  ishmaelwanglin  阅读(212)  评论(0编辑  收藏  举报