0

I'm looking for a more efficient method of monitoring a file from my daemon. I wrote a script which loops to watch a couple of files (/proc/btn_sw1 and /proc/btn_sw2)... I knew looping was a bad idea, I didn't realize how bad it would be.

My daemon is automatically started via the init process, and after it launched I checked the top output and my process was #1 running ~17% CPU constantly:

PID  PPID USER     STAT   VSZ %VSZ  %CPU COMMAND
1698     1 root     S     2196   0%  17% {resetd.sh} /bin/sh /etc/init.d/resetd

My daemon monitors the /proc entries (the value of them is just 1 or 0) which are set by the keypad driver when a hardware button is pressed/released. So I need to know when these file change in value.

Is there a way that I can have my daemon be woken up when the value of the file is changed? Note: I don't want to just sleep for X seconds in between each read because I need to time out how long the button has been pressed for and I don't want to miss the start.

My current daemon code:

#!/bin/sh

proc1file=/proc/btn_sw1
proc2file=/proc/btn_sw2
BTN1VAL=$(cat $proc1file)
BTN2VAL=$(cat $proc2file)

tic=0
elap_time=0
reset_met=0

until [ $reset_met -gt 0 ]
do
  BTN1VAL=$(cat $proc1file)
  BTN2VAL=$(cat $proc2file)
  if [ $BTN1VAL -gt 0 ] && [ $BTN2VAL -gt 0 ]
    then
    tic=`date +%S`

    # Start the 10second loop, I'm ok with reading in here, but before this I'd like
    # to be sleeping or idle instead of constantly polling
    until [ $elap_time -ge 5 ] || [ $BTN1VAL -lt 1 ] || [ $BTN2VAL -lt 1 ]
    do
      BTN1VAL=$(cat $proc1file)
      BTN2VAL=$(cat $proc2file)
      toc=`date +%S`
      elap_time=`expr $toc - $tic`
    done
    if [ $elap_time -ge 5 ]
    then
      reset_met=1
    else
      elap_time=0
    fi
  fi

done
echo "Rebooting!"
reboot -f
Mike
  • 47,263
  • 29
  • 113
  • 177
  • can you check md5 directly? command `md5` or `md5sum` can be used to confirm if the file is changed or not. Performance should be better to cat the file directly. – BMW Feb 21 '14 at 02:25

1 Answers1

0

You'll need the inotify-tools package for this. (Not sure if it will work with /proc files, but it's worth a try).

Something like this:

until [ $reset_met -gt 0 ]
do
    inotifywait "$proc1file" "$proc2file"
    tic=$(date +%S)
    ...
done

Edit: The backquote syntax is obsolete, the recommended syntax is $(command).

Sir Athos
  • 9,403
  • 2
  • 22
  • 23
  • That's the only option? an external package? I was hoping there might be something built. I'm working on an embedded environment so I'll need to get code and cross compile anything extra I include. – Mike Feb 20 '14 at 19:25
  • inotify-tools is just an interface to the inotify subsystem (included in the kernel since 2.6.13). You could also write your own C program that accesses that directly, but I don't know of any shell-builtin facility to do the same thing. – Sir Athos Feb 20 '14 at 19:51
  • A poor man's fix is to add a `sleep 1` call at the end of the main loop, so that you only poll for changes once every second. This may not be an option for you if the timing has to be more exact. – Sir Athos Feb 20 '14 at 19:57