简体   繁体   中英

Terminate cat command immediately after using in C

So I am communicating with a device by using echo to send and cat to receive. Here's a snippet of my code:

fp = popen("echo "xyz" > /dev/ttyACM0 | cat - /dev/ttyACM0", "r");
while (fgets(ret_val, sizeof(ret_val)-1, fp) != NULL)
{
    if (strcmp(ret_val, "response") == 0)
    {
       close(fp);
       return ret_val;
    }
}

Ok, The problem is, cat seems to stay open, because when I run this code in a loop, it works the first time, then hangs at the spot I call popen. Am I correct in assuming cat is the culprit?

Is there a way to terminate cat as soon as I run the command, so I just get the response from my device? Thanks!

In the command:

echo "xyz" > /dev/ttyACM0 | cat - /dev/ttyACM0

TTY devices normally do not open until carrier is present, or CLOCAL is set. The cat could be waiting on open. Assuming the device opens, then the cat will hang waiting to read characters until either (1) it receives an EOF character such as control-D, or (2) carrier is lost or (3) you kill it.

Another problem here is that the pipe between echo and cat immediately closes, because the output of the echo is redirected to the same TTY device, and the redirection closes the pipe.

Generally TTY devices are ornery beasts and require special handling to get the logic right. Probably you are better to read up on TTY devices especially:

man termios

If you are doing something REALLY SIMPLE, you might get by with:

fp = popen("echo 'xyz' >/dev/ttyACM0 & (read x; echo \"$x\")");

Keep in mind that both the echo and the read might hang waiting for carrier and that you will get at most one line of output from the popen, and the read could hang waiting for an EOL character.

This whole approach is fraught with problems. TTY devices require delicate care. You are using a hammer in the dark.

There's no easy way to kill the process launched by popen , as there's no API to get the pid -- there's only pclose which waits until it ends of its own account (and youe should ALWAYS use pclose instead of fclose to close a FILE * opened by popen .)

Instead, you're probably better off not using popen at all -- just use fopen and write what you want with fputs:

fp = fopen("/dev/ttyACM0", "r+");
fputs("xyz\n", fp);   // include the newline explicitly
fflush(fp);           // always flush after writing before reading
while (fgets(ret_val, sizeof(ret_val)-1, fp) != NULL) {
           :

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM