2009-06-07 4 views
0

Я написал код для передачи файловых дескрипторов между несвязанными процессами с использованием потоков. Сервер должен дождаться, когда клиент отправит файловый дескриптор. Вот код сервера:Почему ioctl() не блокируется?

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stropts.h> 
#include <stdio.h> 
#include <errno.h> 
#include <unistd.h> 

int main(int argc, char *argv[]) 
{ 
    int fd; 
    int pipefd[2]; 
    pipe(pipefd); 
    close(pipefd[1]); 
    recvfd(pipefd[0]); 
    return 0; 
} 

void recvfd(int p) 
{ 
    struct strrecvfd rfdbuf; 
    struct stat statbuf; 
    int i; 
    i=ioctl(p, I_RECVFD, &rfdbuf); 
    printf("errno=%d\n",errno); 
    printf("recvfd=%d\n", rfdbuf.fd); 
} 

Но я получаю номер ошибки 9 - Плохой дескриптор файла.

+0

Какую операционную систему вы используете? Трудно ответить на вопрос о вызове ОС, не зная ОС. – Dipstick

+0

Почему, на ваш взгляд, это ошибка? Этот код даже не проверяет возвращаемое значение ioctl. Если он не равен -1, errno не изменяется и может иметь значение из предыдущего системного вызова (например, в динамическом загрузчике или процедурах запуска). – mark4o

ответ

2

Вы не упомянули, какую ОС вы используете. I_RECVFD является частью расширений STREAMS, которые обычно присутствуют только в операционных системах Unixy на базе System V (например, AIX и Solaris). Другие, такие как Linux и BSD, не поддерживают его и, вероятно, никогда не будут, поскольку у Posix теперь есть альтернатива, использующая sendmsg() и recvmsg().

Боюсь, что я не знаю, почему Linux имеет #defines I_RECVFD, если он не поддерживает его.

+0

Мне пришлось использовать ioctl() с fifos (а не с трубками), и, как вы сказали, он не работает в Linux, а работает на Solaris. – Anonymous

0

Это настоящий код? Причина: нигде вы не создаете или не получаете действительный filedescriptor.

2

NB: вопрос был сильно изменен, так как этот ответ был написан.


С чего начать?

  • main() возвращает int.
  • pipefd не инициализирован.
  • Вы закрываете случайный дескриптор файла.
  • Вы вызываете recvfd() на другой случайный файловый дескриптор.
  • Вы не возвращаете значение от main().
  • Вы не используете значение #define.
  • Вы не показываете файлы #include, необходимые для компиляции.
  • Неиспользованная переменная fd.
  • Неиспользованная переменная statbuf.
  • Непроверенное возвращаемое значение i.

Основная проблема - использование неинициализированных переменных.

Дочерняя проблема - ограниченная проверка ошибок.

Дополнительная проблема: концептуально вы хотите сервер, которому можно передать дескриптор файла. Вам нужен этот сервер для чтения из файлового дескриптора, который могут создавать другие (несвязанные) процессы. Вам нужно будет внимательно изучить руководства, но, возможно, понадобится сервер, прослушивающий сокет Unix-домена, или, возможно, чтение на (именуемом) FIFO. Другие программы могут затем открыть сокет или FIFO и отправить их собственный дескриптор файла на сервер.

+0

Технически, это нормально опустить тип возврата из main() (но для main _only_), и в этом случае предполагается 'int '. Точно так же нормально опустить оператор return из main (опять же, main _only_), и в этом случае есть неявное «возвращение 0». Тем не менее, это все еще плохая практика. –

+1

Не в C99, который является текущим стандартом C. В C99 нет типов «неявных int» и т. Д. –

0

Вы никогда не инициализируете pipefd! Отсутствует a

pipe(pipefd); 

линия до close звонок ...?