When the pty [Pseudo terminal] slave fd settings are changed to "tcsetattr", how can the master complete this event without delay?

The slave fd is used by another application (for example, “A”) as a serial port device.

A will set the speed bit / stop bit, etc. My application needs this information.

By the way, is there a way for a process that only the fd open wizard has to notify of all the calls ioctl()that are issued to the slave fd?

+4
source share
1 answer

Yes, this is possible (on Linux and before 2004, FreeBSD) by using pty in batch mode and setting the EXTPROC flag on it.

  • ioctl(master, TIOCPKT, &nonzero). read : , , , - ( " ( ) " )

  • , , , . a select() , ,

  • EXTPROC pty tcsetattr() - select() , , - fd, , , , linux, tcgetattr() .

  • , EXTPROC pty, . .

EXTPROC ( - ), ( shoud at , - linux termios tty_ioctl). linux drivers/tty/n_tty.c, , termios termios select() , tcsetattr(), , .

: J.F. Sebastians , , EXTRPOC linux:

/* Demo program for managing a pty in packet mode with the slave's
** EXTPROC bit set, where the master gets notified of changes in the
** slaves terminal attributes
**   
** save as extproc.c, compile with gcc -o extproc extproc.c -lutil
*/



#include <stdio.h>
#include <pty.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

#define BUFSIZE 512

void main() {
  int master;      // fd of master side
  pid_t pid;
  if((pid = forkpty(&master, NULL, NULL, NULL))) { // we're parent
    fd_set rfds, xfds;
    int retval, nread, status = 0, nonzero = 1;
    char buf[BUFSIZE];

    ioctl(master, TIOCPKT, &nonzero); // initiate packet mode - necessary to get notified of
                                      // ioctl() on the slave side
    while(1) {
      // set stdout unbuffered (we want to see stuff as it happens)                                                                                 
      setbuf(stdout, NULL);

      // prepare the file descriptor sets
      FD_ZERO(&rfds);
      FD_SET(master, &rfds);

      FD_ZERO(&xfds);
      FD_SET(master, &xfds);

      // now wait until status of master changes     
      printf("---- waiting for something to happen -----\n");
      select(1 + master, &rfds, NULL, &xfds, NULL);

      char *r_text = (FD_ISSET(master, &rfds) ? "master ready for reading" : "- ");
      char *x_text = (FD_ISSET(master, &xfds) ? "exception on master" : "- ");

      printf("rfds: %s, xfds: %s\n", r_text, x_text);
      if ((nread = read(master, buf, BUFSIZE-1)) < 0) 
        perror("read error");
      else {         
        buf[nread] = '\0';
        // In packet mode *buf will be the status byte , and buf + 1 the "payload"
        char *pkt_txt = (*buf &  TIOCPKT_IOCTL ? " (TIOCPKT_IOCTL)" : "");
        printf("read %d bytes: status byte %x%s, payload <%s>\n", nread, *buf, pkt_txt, buf + 1);
      }
      if (waitpid(pid, &status, WNOHANG) && WIFEXITED(status)) {
        printf("child exited with status %x\n", status);
        exit(EXIT_SUCCESS);
      } 
    }
  } else { // child
    struct termios tio;

    // First set the EXTPROC bit in the slave end termios structure
    tcgetattr(STDIN_FILENO, &tio);
    tio.c_lflag |= EXTPROC;
    tcsetattr(STDIN_FILENO, TCSANOW, &tio); 

    // Wait a bit and do an ordinary write()
    sleep(1);
    write(STDOUT_FILENO,"blah", 4);

    // Wait a bit and change the pty terminal attributes. This will be picked up by the master end
    sleep(1);
    tio.c_cc[VINTR] = 0x07; 
    tcsetattr(STDIN_FILENO, TCSANOW, &tio);

    // Wait a bit and exit
    sleep(1);
  } 
}

:

---- waiting for something to happen -----
rfds: master ready for reading, xfds: exception on master
read 1 bytes: status byte 40 (TIOCPKT_IOCTL), payload <>
---- waiting for something to happen -----
rfds: master ready for reading, xfds: - 
read 5 bytes: status byte 0, payload <blah>
---- waiting for something to happen -----
rfds: master ready for reading, xfds: exception on master
read 1 bytes: status byte 40 (TIOCPKT_IOCTL), payload <>
---- waiting for something to happen -----
rfds: master ready for reading, xfds: - 
read error: Input/output error
child exited with status 0

, - pty tty ( termios), Linux ( termios: termios ).

, EXTPROC , .

, , , .

+4

Source: https://habr.com/ru/post/1525897/


All Articles