シェルスクリプトとttyリークメモリ

シェルスクリプトとttyリークメモリ

私はArduinoと通信するためにラズベリーパイでシェルスクリプトを実行しています。私のメモリは1時間あたり約50MBを消費します。

スクリプト自体は単にttyACM0(arduinoのUSB端子)に接続し、ここに文字を送信します。スクリプトは1分ごとに実行され、一時値を確認します。最初のパラメーターの値は、「a」、「b」、または「T」です。 「a」または「b」の場合、リレーのオン/オフを切り替えます。 「T」の場合、Arduinoは私が保存した3つの温度値を返します。

スクリプトはうまく機能します(arduinosシリアルポートを再起動しなくてもリレーを制御して値を受け取ることができます)。しかし、限られたメモリが原因で問題が発生します。

私のデバイスで実行されている他のプロセスはなく、新しいRaspbian設定を試しました。

誰かがこのスクリプトでメモリリークがどこにあるのか、そしてこれを防ぐ方法を教えてもらえますか?

編集:時間の経過とともに何百もの「cat」コマンドを実行するスクリプトである犯人を見つけました。どのように削除しますか?私はkillall catを試しましたが、これは私のラズベリーパイシリアル接続をリセットします(arduinoを「再起動」するので無効にしたい!)@mikeservは定義された行を読み取るヘッドを使用すると指摘しました。数秒後に自動的に終了します。残念ながら動作しません。パイプなしでは出力ファイルに温度を書き込むことができないようです。

head -n3 <&3 >>/home/pi/output

終了せず出力も出ないので動作しません。

メモリを解放するために数分ごとにすべての猫を殺すことができますが、そうすると私のttyもarduinoにリセットされます(再起動するとリレー状態が失われます)。

Edit2:私はこれを動作させませんでした(ミニコム、スクリーンなどを含むいくつかの可能性を試しました...)。しかし、受信部分に問題があります。しかし、Arduinoに文字を送ることは素晴らしい仕事です!

#!/bin/bash

# READ / WRITE ARDUINO

exec 3<> /dev/ttyACM0

echo "connected, sleep for 1 sec..."
sleep 1

echo "send $1..."

echo "$1" >&3

if [ "$1" = "T" ]
then
        cat <&3 | cat >> /home/pi/output &2>1
else
        echo "nothing to save"
fi

echo "closing.."

exec 3>&-

exit 0

答え1

時:

exec 3<> /dev/ttyACM0

... 3のUSBシリアルttyの読み取り/書き込みファイル記述子を開きます。これはサブアイテム(たとえば、複製されたサブシェル)によって自動的に継承されるため、cat <&3後でバックグラウンドパイプから読み取ることができます。

しかし、問題はパイプがバックグラウンドに配置されるため、パイプに関連するすべてのサブシェルが別々のプロセスグループに配置されるため、後でパイププロセスが閉じられないことです。

exec 3<&-

...現在のシェルプロセスのスクリプト記述子を閉じます。代わりに...

cat </dev/ttyACM0 | cat >> file &

...バックグラウンドにぶら下がっていて、何も読まない限り何も読みません。これはcat、入力がEOFでのみ終了し、その場合、入力を受信しないためです。

あなたはできます:

cat /dev/tty

... プロンプトに従って動作を概説します。

あなたがしなければならないことは、必要な内容を読むとすぐに入力を明示的に終了するか、読んだcat後に入力を明示的に終了することです。次のことができます。

head -n"$GUARANTEED_NUM_AVAIL_INPUT LINES" <&3 >>file

...またはまたはsed [num]q同様です。これは完全に実行するのを避ける必要があり、|pipeおそらく&背景を完全に省略する可能性があります。それ以外の場合は、殺すために次のことがcatできます。

cat <&3 >>file &
sleep 1 && kill "$!"

...しかし、入力を終了する方がはるかに簡単なので、これは必要ないかもしれません。

しかし、スクリプトが既に移植可能な構文で完全に構成されていることは注目に値するので、その行を変更して#!/bin/bashより軽量で高速なシェルを呼び出すことが価値があるかもしれません。私はdashこのようなことをお勧めします。見るここbashおよびを含むさまざまなシェル間のパフォーマンス比較に関するQ&Aに興味がある場合dash

答え2

修正を作成することはできませんが、何が起こっているのかを説明できます。

  1. 港を開いています。
  2. 温度センサーの値を確認/送信します。
  3. ポートを閉じています。

いくつかの可能性:

  • ArduinoのUSBバッファはスクリプトを再度実行するまで入力され続けますが、バッファは最後の実行以降もいっぱいです。前回の実行数がバッファに蓄積され、通信ポートにバッファオーバーフローが発生しました。
  • 他の方向でも同じ方法でバッファが満たされるため、Raspberry Piでも同じ問題が発生します。

ドアが開いて、3を送り、閉じ、開いて、3を送って、閉じるように両方のバッファをクリアする方法を見つける必要があります。 Yetiが提案したように、Subshel​​lingは1つのアプローチです。バッファを閉じてもう一度開いたが、CommPortを終了しないなどの他の方法があると確信しています。私は通信ドライバーの専門家ではないので、理論だけを提示します。

修正する

If [ "$1" = "T" ]
then
        cat <&3 | cat >> /home/pi/output &2>1
        cat <&3 | cat >> /dev/null
else
        echo "nothing to save"
        cat <&3 | cat >> /dev/null
fi

関連情報