2013-08-02 13 views
11

In uno script bash, provo a leggere le righe da input standard, utilizzando il comando integrato read dopo aver impostato IFS=$'\n'. Le righe vengono troncate al limite di 4095 caratteri se si incolla l'input nella lettura. Questa limitazione sembra provenire dalla lettura dal terminale, perché questo ha funzionato perfettamente bene:Terminale Linux input: lettura input utente da linee di troncamento terminali con limite di caratteri 4095

fill= 
for i in $(seq 1 94); do fill="${fill}x"; done 
for i in $(seq 1 100); do printf "%04d00$fill" $i; done | (read line; echo $line) 

provo lo stesso comportamento con script Python (non accettava più di 4095 di ingresso dal terminale, ma accettato dal tubo):

#!/usr/bin/python 

from sys import stdin 

line = stdin.readline() 
print('%s' % line) 

programma Anche C funziona allo stesso, utilizzando read(2):

#include <stdio.h> 
#include <unistd.h> 

int main(void) 
{ 
    char buf[32768]; 
    int sz = read(0, buf, sizeof(buf) - 1); 
    buf[sz] = '\0'; 
    printf("READ LINE: [%s]\n", buf); 
    return 0; 
} 

In tutti i casi, non posso entrare più lungo di circa 4095 caratteri. Il prompt di input smette di accettare caratteri.

Question-1: C'è un modo per leggere interattivamente dal terminale più di 4095 caratteri nei sistemi Linux (almeno Ubuntu 10.04 e 13.04)?

Question-2: Da dove viene questa limitazione?

Sistemi interessati: ho notato questa limitazione in Ubuntu 10.04/86 e 13.04/86, ma Cygwin (versione recente almeno) non troncare ancora a più di 10000 caratteri (non prova più da quando ho bisogno di ottenere questo script funzionante in Ubuntu). Terminali utilizzati: Virtual Console e KDE konsole (Ubuntu 13.04) e gnome-terminal (Ubuntu 10.04).

risposta

-1

Non ho una soluzione per te, ma posso rispondere alla domanda 2. In linux PIPE_BUF è impostato su 4096 (in limits.h) Se fate una scrittura di più di 4096 ad un tubo sarà troncato.

Da /usr/include/linux/limits.h:

#ifndef _LINUX_LIMITS_H 
#define _LINUX_LIMITS_H 

#define NR_OPEN   1024 

#define NGROUPS_MAX 65536 /* supplemental group IDs are available */ 
#define ARG_MAX  131072 /* # bytes of args + environ for exec() */ 
#define LINK_MAX   127 /* # links a file may have */ 
#define MAX_CANON  255 /* size of the canonical input queue */ 
#define MAX_INPUT  255 /* size of the type-ahead buffer */ 
#define NAME_MAX   255 /* # chars in a file name */ 
#define PATH_MAX  4096 /* # chars in a path name including nul */ 
#define PIPE_BUF  4096 /* # bytes in atomic write to a pipe */ 
#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */ 
#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */ 
#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */ 

#define RTSIG_MAX  32 

#endif 
+0

Sì, esiste una tale limitazione per pipe e in realtà è rilevante notare che il valore non interattivo la versione usa le pipe e per necessità ci saranno _siverse scritture e letture_. Ma penso che questo limite non dovrebbe influenzare l'ingresso del terminale (i terminali non sono tubi). – FooF

7

Questo è risposta parziale. Impostazione del terminale in modalità non canonica consente di leggere più di 4096 caratteri (dove il carattere # 4096 deve essere una nuova riga).

In uno script bash questo può essere fatto in questo modo:

IFS=$'\n'  # Allow spaces and other white spaces. 
stty -icanon # Disable canonical mode. 
read line  # Now we can read without inhibitions set by terminal. 
stty icanon # Re-enable canonical mode (assuming it was enabled to begin with). 

Dopo questa modifica di aggiungere stty -icanon è possibile incollare più di 4096 stringa di caratteri e leggerlo con successo bash built-in read comando (I con successo provato più di 10000 caratteri).

Il limite per il buffer della linea terminale è probabilmente impostato da qualche kernel.

TODO:

  1. programma C per dimostrare questo (utilizzando tcgetattr() e tcsetattr())
  2. di prova con l'architettura/Linux x86_64 - potrebbe avere limite diverso.
  3. Trova dove nel kernel è definito (forse N_TTY_BUF_SIZE definito in ${linux_source_path}/include/linux/tty.h).
-1

Il problema non è sicuramente il read(); in quanto può leggere fino a qualsiasi valore intero valido. Il problema deriva dalla memoria heap o dalle dimensioni del tubo .. poiché sono gli unici possibili fattori limitanti alle dimensioni.

+0

No, il problema è la dimensione del buffer per la modalità canonica del terminale. La riga di input è 4096 (l'ultimo byte riservato per la nuova riga). Questo è spiegato e dimostrato nella risposta dall'interrogante originale. Sta dicendo che la risposta non è completa perché non ha ancora avuto il tempo di scrivere un programma in C per dimostrarlo, e non ha potuto indicare dove nel kernel è definito questo limite. – FooF

+0

Questo è quello che sto cercando di dire, la dimensione del buffer pipe è 4096. Può essere controllata usando "ulimit -p" restituirà 8 come risposta, che significa 8 * 512 byte = 4096. Poiché ogni carattere è 1 byte, quindi legge solo 4095 byte e l'ultimo carattere come newline come hai detto tu. – Abhishek

+1

Penso che sia una costante diversa. Come succede 4096 è la dimensione della pagina predefinita, spiegando perché il valore si verifica essere lo stesso per la dimensione massima del tubo e il buffer di input del terminale in modalità canonica. – FooF