为了账号安全,请及时绑定邮箱和手机立即绑定

在 Go 中读取命名管道时 CPU 使用率 100%

在 Go 中读取命名管道时 CPU 使用率 100%

Go
白猪掌柜的 2021-09-13 14:50:09
我有一个简短的 Go 程序,它从命名管道中读取数据,并在外部进程写入管道时处理每一行。命名管道是在程序运行之前创建的mkfifo。该进程在等待来自命名管道的新行时占用了 100% 的 CPU,即使它没有进行任何处理。它在 Ubuntu 14.04 上运行。有任何想法吗?c := make(chan os.Signal, 1)signal.Notify(c, os.Interrupt, syscall.SIGTERM)awaitingExit := falsevar wg sync.WaitGroupgo func() {    for sig := range c {        awaitingExit = true        // wait for goroutines to finish processing new lines        wg.Wait()        os.Exit(1)    }}()file, err := os.OpenFile("file.fifo", os.O_RDONLY, os.ModeNamedPipe)defer file.Close()if err != nil {    log.Fatal(err)}reader := bufio.NewReader(file)// infinite loopfor {    line, _, _ := reader.ReadLine()    // stop handling new lines if we're waiting to exit    if !awaitingExit && len(line) > 0 {        wg.Add(1)        go func(uploadLog string) {            defer wg.Done()            handleNewLine(uploadLog)        }(string(line))    }}func handleNewLine(line string) {    ....}
查看完整描述

1 回答

?
达令说

TA贡献1821条经验 获得超6个赞

你的“无限循环”真的是无限的:你永远不会退出或跳出它。


它包含一个if:


// stop handling new lines if we're waiting to exit

if !awaitingExit && len(line) > 0 {

    // code omitted

}

但是如果条件为假,您仍然没有退出for循环,只需继续另一个迭代。一旦到达结束reader,此循环将消耗 100% 的核心,因为之后它不会等待任何尝试读取(将立即返回 EOF)并检查awaitExit变量并再次执行这两个步骤的任何内容。


您要么需要向for循环添加条件以在某个时候退出,要么使用break语句来中断它。


for有条件的改变循环:


for !awaitingExit {

}

更改for为break声明:


for {

    if awaitingExit {

        break

    }

    // code omitted

}

注意:如果awaitingExit变量被另一个 goroutine 改变,你需要适当的同步,或者更好的是,使用通道来发出退出信号。


查看完整回答
反对 回复 2021-09-13
  • 1 回答
  • 0 关注
  • 341 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信