2017-01-09 4 views
0

Ich habe einen psuedo Terminal auf Linux C ausgeführt wird, geöffnet, wie gezeigt:Verwenden von Termios(), um EOF zu ersetzen?

else 
{ 
    struct termios slave_orig_term_settings; // Saved terminal settings 
    struct termios new_term_settings; // Current terminal settings 

    // CHILD 
    close(fdm); 

    rc = tcgetattr(fds, &slave_orig_term_settings); 

    new_term_settings = slave_orig_term_settings; 

    new_term_settings.c_cc[VEOF] = '|'; 
    new_term_settings.c_oflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | ICRNL); 

    cfmakeraw (&new_term_settings); 

    tcsetattr (fds, TCSANOW, &new_term_settings); 

} 

Wenn aus dem Rohr zu lesen, kann ich ein nicht blockierende machen read(), die nach der Rückkehr werden, beispielsweise 5 Sekunden. Das Problem ist, dass wenn ich einen Befehl wie "ls" ausführe, der in mehreren ms zurückkehrt, wird er die vollen 5 Sekunden warten, bevor er zurückkehrt.

Ich verstehe, mit einem physischen GUI-Terminal, und nicht ein Pseudo-Terminal wie folgt, kann der Benutzer STRG drücken^D und EOF am Ende jeder Ausgabe gesendet haben.

Ich möchte diesen Effekt, so kann mein Programm sagen: "OK, ich habe dieses bestimmte Byte empfangen, was bedeutet, dass das Terminal fertig ist, auszugeben, und ich kann diese Ausgabe jetzt zurück zum Anrufer bringen, und ich weiß, dass es keine gibt mehr Ausgabe zum Lesen ".

Ich verstehe, dass dies mit der Funktion termios() getan wird (oder es ist Wrapper stty), aber ich kann es nicht funktionieren. Ich möchte, dass das Terminal mir das '|' char anstelle von ctrl^d (\ x04) nach Beendigung der Ausgabe, aber es funktioniert nicht.

Aus Gründen der Klarheit, nach Abschluss der Ausgabe (über read()), möchte ich das '|' Byte. Also, wenn ich ‚pwd‘ Befehl senden, erhalte ich diese Ausgabe:

$ pwd 
/home/user/dir 
$| 

Könnte jemand bitte sagen Sie mir, wie man diesen Code bearbeiten, um diesen Effekt zu acheive?

Danke für Ihre Hilfe.

EDIT - select() Code

while ((bytes = select(pipe + 1, &fd_in, NULL, NULL, &tv))) 
{  
      if (FD_ISSET(pipe, &fd_in)) 
      { 

       read (pipe...) 

Das Verhalten des obigen Code ist, wie ich beschrieben habe, für den vollen Wert von tv zu warten, auch wenn es nichts auf dem Rohr ist, vor der Rückkehr .

+0

Die '.c_cc [VEOF]' Sonderzeichen nur in "kanonischen" -Modus ('ICANON' in' .c_lflags' Bit gesetzt) ​​verwendet wird, aber 'cfmakeraw' "raw" -Modus setzt (' ICANON' Bit nicht eingestellt). –

Antwort

1

Der Wert von c_cc[VEOF] wird niemals an Sie gesendet werden. Beispielsweise ist der Standardwert c_cc[VEOF]CTRL-D, aber Sie werden nicht die CTRL-D am Ende der Datei sehen, wenn der Benutzer CTRL-D drückt. Stattdessen werden Sie benachrichtigt (z. B. durch read() mit der Rückgabe 0), dass Sie das Ende der Datei erreichen.

Normalerweise, wenn das Kind mit seiner Arbeit fertig ist, wird es explizit close() die Pty Slave-Seite, so dass die Pty Masterseite erhalten EOF.

Bezüglich mir eine nicht blockierende Lese machen kann(), die nach dem zurückkehren, zum Beispiel 5 Sekunden. Das Problem ist, dass wenn ich einen Befehl wie "ls" ausführe, der in mehreren ms zurückkehrt, , wird es die vollen 5 Sekunden warten, bevor er zurückgibt.

nicht sicher, wie Sie den Code schreiben, aber Sie können select() oder poll() verwenden, die Sie sofort benachrichtigen können, wenn gibt es Daten zum Lesen zur Verfügung.


Nach select() ‚s Manpage:

select() und pselect() erlauben ein Programm mehrere Dateideskriptoren zu überwachen, werden , bis eine oder mehrere der Filedeskriptoren warten‚ready‘ für einige Klasse der E/A-Operation (z. B. Eingabe möglich). Ein Dateideskriptor wird als bereit betrachtet, wenn es möglich ist, eine entsprechende E/A-Operation (z. B. read(2) ohne Blockierung oder eine ausreichend kleine write(2)) durchzuführen.

+0

Das habe ich befürchtet. Ich verwende ein nicht blockierendes read() über select(). Gibt es eine Möglichkeit, zu veranlassen, dass read() 0 zurückgibt, ohne auf den Wert zu warten, der in timeval definiert wurde, um select() auf dem read() - Dateideskriptor zu übergeben? Ich möchte vermeiden, auf den vollen Wert von timeval zu warten, um auszuwählen, ob das Programm davor zurückkehrt. Danke für Ihre Hilfe. – termquestion

+0

Sie können '.c_cc [VTIME]' setzen, um ein Zeitlimit in Dezisekunden im "rohen" (nicht-kanonischen) Modus einzustellen. –

+0

Ich sehe auf einer anderen Frage, dass VTIME keine Auswirkungen auf nicht blockierende Sockets hat. – termquestion

Verwandte Themen