go - 读取 /dev/gpiomem 时 CPU 使用率高
问题描述
我的 Golang 代码中有什么东西会导致 CPU 使用率过高吗?
该代码应读取 Raspberry Pi 4 (4GB) 上 GPIO 引脚上的按钮,并在按下时将 REST 发布消息发送到另一个程序。
我尝试使用更多睡眠和不睡眠,我尝试更改代码以在引脚上使用下降沿检测方法。没有什么改变高 CPU 使用率。
import (
"fmt"
"github.com/stianeikeland/go-rpio"
"os"
"io/ioutil"
"net/http"
"strings"
"time"
)
func main() {
fmt.Println("Starting Stream Control 0.1")
pinOpenError := rpio.Open()
if pinOpenError != nil {
fmt.Println("Pin Open Error: ", pinOpenError.Error())
os.Exit(1)
}
pin := rpio.Pin(18)
pin.Input()
pin.PullUp()
var PID string
start := time.Now()
StreamRunning := false;
fmt.Println("Reading and Controlling")
for {
res := pin.Read()
if res == 0 {
if StreamRunning == false && time.Since(start).Seconds() > 10{
var StartStreamError error
PID, StartStreamError = StartStream()
if StartStreamError != nil {
fmt.Println("Start Stream Error: ", StartStreamError.Error())
}
fmt.Println("PID = " + PID)
start = time.Now()
StreamRunning = true;
} else {
if time.Since(start).Seconds() > 10 {
StopStream(PID)
StreamRunning = false;
start = time.Now()
}
}
}
time.Sleep(100)
}
}
func postHTTP(url string, requestString string) ([]byte, error){
var blankBody []byte
payload := strings.NewReader(requestString)
client := &http.Client{}
req, clientError := http.NewRequest("POST", url, payload)
if clientError != nil {
return blankBody, clientError
}
req.Header.Add("Content-Type", "application/json")
res, requestError := client.Do(req)
if requestError != nil {
return blankBody, requestError
}
defer res.Body.Close()
returnBody, returnError := ioutil.ReadAll(res.Body)
return returnBody, returnError
}
func StartStream()(string, error) {
fmt.Println("Start Stream")
response, StreamOnError := postHTTP("http://localhost:3000/startStream","{\"devicePath\":\"/dev/video0\",\"streamName\":\"LumiPi-003\"}")
if StreamOnError != nil {
fmt.Println("Stream On Error: ", StreamOnError.Error())
return "0", StreamOnError
}
splitstrings := strings.Split(string(response),",")
for i := range splitstrings {
if strings.Contains(splitstrings[i], "\"pid\":") {
linesplit := strings.Split(splitstrings[i],":")
return linesplit[1], nil
}
}
return "0", nil
}
func StopStream(PID string)(error) {
fmt.Println("Stop Stream")
command := "{\"pid\":" + PID + "}"
_, StreamOnError := postHTTP("http://localhost:3000/stopStream",command)
if StreamOnError != nil {
fmt.Println("Stream Off Error: ", StreamOnError.Error())
return StreamOnError
}
return nil
}
下图显示了 time.sleep 对程序的影响。
解决方案
当 rpio.Open() 仍然打开时,time.Sleep() 函数导致 PI 崩溃。
打开、读取引脚和关闭允许 time.Sleep() 以更大的延迟使用,这反过来又降低了 cpu 使用率,因为它不是不断循环。
import (
"fmt"
"github.com/stianeikeland/go-rpio"
"os"
"io/ioutil"
"net/http"
"strings"
"time"
)
func main() {
fmt.Println("Starting Stream Control 0.1")
var PID string
start := time.Now()
StreamRunning := false;
fmt.Println("Reading and Controlling")
for {
pinOpenError := rpio.Open()
if pinOpenError != nil {
fmt.Println("Pin Open Error: ", pinOpenError.Error())
os.Exit(1)
}
pin := rpio.Pin(18)
pin.Input()
pin.PullUp()
res := pin.Read()
rpio.Close()
if res == 0 {
if StreamRunning == false && time.Since(start).Seconds() > 10{
var StartStreamError error
PID, StartStreamError = StartStream()
if StartStreamError != nil {
fmt.Println("Start Stream Error: ", StartStreamError.Error())
}
fmt.Println("PID = " + PID)
start = time.Now()
StreamRunning = true;
} else {
if time.Since(start).Seconds() > 10 {
StopStream(PID)
StreamRunning = false;
start = time.Now()
}
}
}
time.Sleep(100*time.Millisecond)
}
}
func postHTTP(url string, requestString string) ([]byte, error){
var blankBody []byte
payload := strings.NewReader(requestString)
client := &http.Client{}
req, clientError := http.NewRequest("POST", url, payload)
if clientError != nil {
return blankBody, clientError
}
req.Header.Add("Content-Type", "application/json")
res, requestError := client.Do(req)
if requestError != nil {
return blankBody, requestError
}
defer res.Body.Close()
returnBody, returnError := ioutil.ReadAll(res.Body)
return returnBody, returnError
}
func StartStream()(string, error) {
fmt.Println("Start Stream")
response, StreamOnError := postHTTP("http://localhost:3000/startStream","{\"devicePath\":\"/dev/video0\",\"streamName\":\"LumiPi-003\"}")
if StreamOnError != nil {
fmt.Println("Stream On Error: ", StreamOnError.Error())
return "0", StreamOnError
}
splitstrings := strings.Split(string(response),",")
for i := range splitstrings {
if strings.Contains(splitstrings[i], "\"pid\":") {
linesplit := strings.Split(splitstrings[i],":")
return linesplit[1], nil
}
}
return "0", nil
}
func StopStream(PID string)(error) {
fmt.Println("Stop Stream")
command := "{\"pid\":" + PID + "}"
_, StreamOnError := postHTTP("http://localhost:3000/stopStream",command)
if StreamOnError != nil {
fmt.Println("Stream Off Error: ", StreamOnError.Error())
return StreamOnError
}
return nil
}
推荐阅读
- powershell - 将 Web 请求导出到 CSV 不会正确创建表头
- reactjs - 反应生命周期:阶段
- javascript - 控制器更改后,离子日期时间不会更新视图值
- python - Python的upper()方法的奇怪行为
- dart - 飞镖有运算符>>>吗?
- ios - 关闭 UIHostingController 中包含的 SwiftUI 视图
- javascript - 尝试使用 Firebase 登录时出现 403:restricted_client
- android - 滑动时 ItemTouchHelper 不更新项目
- java - 我可以让 Filter getFilter() 方法更改多个列表吗?
- java - HikariCP Spring Boot APP 使 Postgresql 连接完成