STDIN_FILENO и STDOUT_FILENO только для чтения в c? - PullRequest
2 голосов
/ 01 июня 2011
fd = open("/dev/null", O_RDWR);
if (fd == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                  "open(\"/dev/null\") failed");
    return NGX_ERROR;
}

if (dup2(fd, STDIN_FILENO) == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
    return NGX_ERROR;
}

if (dup2(fd, STDOUT_FILENO) == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
    return NGX_ERROR;
}


if (fd > STDERR_FILENO) {
    if (close(fd) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
        return NGX_ERROR;
    }
}

man говорит мне, что dup2() makes newfd be the copy of oldfd, closing newfd first if necessary.:

int dup2(int oldfd, int newfd);

Но не STDIN_FILENO и STDOUT_FILENO только для чтения?

Dump of assembler code for function dup2:
0x00000037aa4c6ac0 <dup2+0>:    mov    $0x21,%eax
0x00000037aa4c6ac5 <dup2+5>:    syscall 
0x00000037aa4c6ac7 <dup2+7>:    cmp    $0xfffffffffffff001,%rax
0x00000037aa4c6acd <dup2+13>:   jae    0x37aa4c6ad0 <dup2+16>
0x00000037aa4c6acf <dup2+15>:   retq   
0x00000037aa4c6ad0 <dup2+16>:   mov    0x28a4d1(%rip),%rcx        # 0x37aa750fa8 <free+3356736>
0x00000037aa4c6ad7 <dup2+23>:   xor    %edx,%edx
0x00000037aa4c6ad9 <dup2+25>:   sub    %rax,%rdx
0x00000037aa4c6adc <dup2+28>:   mov    %edx,%fs:(%rcx)
0x00000037aa4c6adf <dup2+31>:   or     $0xffffffffffffffff,%rax
0x00000037aa4c6ae3 <dup2+35>:   jmp    0x37aa4c6acf <dup2+15>

Или dup2 совсем не изменился newfd?

Ответы [ 3 ]

3 голосов
/ 01 июня 2011

Сами константы (в POSIX STDIN_FILENO это 0 и STDOUT_FILENO это 1) действительно доступны только для чтения, но дескрипторы файлов, которые они характеризуют, могут быть закрыты, а на их месте может быть открыто что-то еще;это просто обычные файловые дескрипторы (обычно с установленным флагом, чтобы они оставались открытыми при системном вызове execve()).

Что меняется, так это таблица файловых дескрипторов для процесса, который находится внутриядро ОС.Видите эту syscall инструкцию?Это действительно важно здесь;это ловушка вашего процесса в ОС.

3 голосов
/ 01 июня 2011

Это заключительная часть демонизации, включающая перенаправление stdout и stdin на /dev/null, потому что они не будут использоваться позже.

Демоны обычно записывают в файлы журнала, а не встандартный вывод.

Цитирование этой статьи :

После запуска демон не должен выполнять чтение или запись в терминал, с которого он был запущен.Самый простой и эффективный способ обеспечить это - закрыть файловые дескрипторы, соответствующие stdin, stdout и stderr.Затем их нужно открыть либо в / dev / null, либо, если они предпочтительнее, в каком-либо другом месте.Есть две причины не оставлять их закрытыми:

  • для предотвращения сбоя кода, который ссылается на эти файловые дескрипторы, и
  • для предотвращения повторного использования дескрипторов для каких-либо других целей.
0 голосов
/ 01 июня 2011

Закрытие stdin и stdout работает отлично. Хотя, когда вы делаете это, вы больше не можете читать их и должны использовать дескрипторы dup ().

...