gpt4 book ai didi

go - go 中的 Fcntl 不起作用

转载 作者:IT王子 更新时间:2023-10-29 01:38:28 25 4
gpt4 key购买 nike

我目前正在编写一个 http 服务器,它必须运行一个文件夹中的所有文件。一个请求可以写入一个文件,而另一个请求可以同时读取文件,所以我需要锁定文件,该文件已打开以供写入。在例程中,将读取文件,我只想跳过被锁定的文件。为此,我想使用来自 rubyist 的锁库或 nightlyone .

问题是,我没有让它们工作,所以我开始自己调用 syscall.FcntlFlock() 函数,但它没有像我预期的那样工作。
该程序在 Go Playground 中不起作用,因为 playground 似乎不在基于 unix 的系统上运行(syscall.FcntlFlock 未定义)

无效的代码:

func main() {
time.Sleep(time.Second)

file, err := os.Open("lockfiletest.lock")
if err != nil {
log.Printf("error opening file2: %s", err)
return
}
defer file.Close()

flockT := syscall.Flock_t{
Type: syscall.F_WRLCK,
Whence: io.SeekStart,
Start: 0,
Len: 0,
}
err = syscall.FcntlFlock(file.Fd(), syscall.F_SETLK, &flockT)
if err != nil {
log.Printf("error locking file2: %s", err)
return
}

log.Println("lock2 accessed")

time.Sleep(time.Second * 5)

log.Println("func2 finished")

time.Sleep(time.Second * 15)
}

控制台输出:

2017/10/28 00:18:12 error locking file2: bad file descriptor
Process finished with exit code 0

我做错了什么?系统调用是否损坏?
我也在 C 中尝试过,它工作正常。
我在 ubuntu16.04 上的 Go1.8.3 和 Go1.9.1 测试了这个程序

PS:这个程序也必须在windows上运行,所以只实现一个FcntlLock是不够的。


我还想使用 sync.RWMutex,因此它是通过 Mutex 而不是 fileLock 锁定的。这不是我想要的,因为我只想跳过被锁定的文件,而不是等到互斥量被锁定。

最佳答案

如果我使用 touch lockfiletest.lock 创建文件,即没有文件内容,您的程序将失败并出现错误:error locking file2: bad file descriptor

$ rm -f lockfiletest.lock
$ touch lockfiletest.lock
$ go run lockfiletest.go
2017/10/27 21:17:27 error locking file2: bad file descriptor

我更改了打开的文件以紧密匹配 TestFcntlFlock

$ uname -s
Linux
~/go/src/syscall$ $ go test -v -run=TestFcntlFlock syscall_unix_test.go
=== RUN TestFcntlFlock
--- PASS: TestFcntlFlock (0.01s)
PASS
ok syscall 0.008s
~/go/src/syscall$

例如,

package main

import (
"io"
"log"
"os"
"syscall"
"time"
)

func main() {
time.Sleep(time.Second)

name := "lockfiletest.lock"
file, err := os.OpenFile(name, syscall.O_CREAT|syscall.O_RDWR|syscall.O_CLOEXEC, 0666)
if err != nil {
log.Printf("error opening file: %s", err)
return
}
defer file.Close()

flockT := syscall.Flock_t{
Type: syscall.F_WRLCK,
Whence: io.SeekStart,
Start: 0,
Len: 0,
}
err = syscall.FcntlFlock(file.Fd(), syscall.F_SETLK, &flockT)
if err != nil {
log.Printf("error locking file: %s", err)
return
}

log.Println("lock2 accessed")

time.Sleep(time.Second * 5)

log.Println("func2 finished")

time.Sleep(time.Second * 15)
}

输出:

$ rm -f lockfiletest.lock
$ touch lockfiletest.lock
$ go run lockfiletest.go
2017/10/27 21:21:56 lock2 accessed
2017/10/27 21:22:01 func2 finished
$ rm -f lockfiletest.lock
$ go run lockfiletest.go
2017/10/27 21:22:25 lock2 accessed
2017/10/27 21:22:30 func2 finished
$ go run lockfiletest.go
2017/10/27 21:25:40 lock2 accessed
2017/10/27 21:25:45 func2 finished
$

关于go - go 中的 Fcntl 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46984411/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com