fredericopissarra Posted April 5, 2019 at 02:39 PM Share Posted April 5, 2019 at 02:39 PM Se você der uma olhada nas manpages de funções como open() e socket(), verá que elas retornam o file descriptor, um inteiro, sinalizado, que corresponde ao "arquivo" aberto. Mas, ambas páginas te dizem que o valor de retorno -1 é um código de erro. No entanto, já vi código assim: int fd; if ( ( fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) < 0 ) { ... trata erro aqui ... } Estritamente falando, essa comparação com 0 é errada. O valor correspondente a erro é -1 e, em teoria, qualquer outro valor negativo poderia ser usado como um descritor válido. Mas, dando uma olhada na descrição da função, lemos: Citar socket() creates an endpoint for communication and returns a file descriptor that refers to that endpoint. The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process. Negrito meu. Só nos resta entender qual seria esse "menor valor numérico". Isso pode ser obtido na descrição da função open(): Citar The return value of open() is a file descriptor, a small, nonnegative integer that is used in subsequent system calls. Negrito também meu... Então, um file descriptor, quando válido, é sempre positivo. Isso implica que a comparação contra zero é perfeitamente válida e torna nosso código menor. Eis um exemplo do dump de duas funções simples: ; int f( int x ) { return x == -1; } f: 0: 31 c0 xor eax,eax 2: 83 ff ff cmp edi,0xffffffff 5: 0f 94 c0 sete al 8: c3 ret ; int g( int x ) { return x < 0; } g: 0: 89 f8 mov eax,edi 2: c1 e8 1f shr eax,31 5: c3 ret Tudo o que a função g() precisa fazer é verificar o sinal de x, daí o deslocamento de 31 bits para a esquerda do valor de EAX. A função f(), embora não seja assim tão ruim, realiza uma operação aritmética (CMP) e altera EAX em dois pontos, já g() apenas faz a alterção de EAX... Sem contar que g() gasta 4 bytes a menos nas instruções, colocando menos pressão no cache L1i. Existe um limite superior, default, para a quantidade de descritores que podem ser abertos por processo: $ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 31542 max locked memory (kbytes, -l) 16384 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 31542 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited Veja a linha "open files". No máximo, por default, um processo pode abrir até 1024 descritores. Destes, temos que descontar os 3 descritores default (stdin, stdout e stderr; 0, 1 e 2, respectivamente), restando 1021 descritores disponíveis para um processo. Assim, um file descritor não ocupará mais que 10 bits de tamanho se esse limite não for alterado e, mesmo que seja, um int tem 31 bits de precisão, possibilitando o valor máximo de um descritor de 2³¹-1 ou 2147483647 arquivos abertos por processo (isso é um exagero e se for permitido e essa quantidade alcançada, consumirá muita memória e tornará seu sistema lentíssimo!). Então, comparar a condição de erro contra 0 e não contra -1, é perfeitamente seguro. A não ser que você queira que seu código seja totalmente portável... Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.