ioctl дает неверный аргумент

Я хочу отправить дескриптор открытого файла между двумя разными программами. Поэтому я использую ioctl с named pipes для этого. Но там я получаю неверный аргумент для ioctl.

#include <stropts.h>
#include "accesories.c"
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>

#define MSGSIZ 63
char *fifo = "fifo";

int send_err(int fd, int errcode, const char *msg)
{
    int     n;

    if ((n = strlen(msg)) > 0)
        if (write(fd, msg, n) != n)    /* send the error message */
            return(-1);

    if (errcode >= 0)
        errcode = -1;   /* must be negative */

    if (send_fd(fd, errcode) < 0)
        return(-1);

    return(0);
}

int send_fd(int fd, int fd_to_send)
{
    char    buf[2];     /* send_fd()/recv_fd() 2-byte protocol */

    buf[0] = 0;         /* null byte flag to recv_fd() */
    if (fd_to_send < 0) {
        buf[1] = -fd_to_send;   /* nonzero status means error */
        if (buf[1] == 0)
            buf[1] = 1; /* -256, etc. would screw up protocol */
    } else {
        buf[1] = 0;     /* zero status means OK */
    }
    //printf("From the write %d\n",buf[0]);
    if (write(fd, buf, 2) != 2)
        return(-1);

    if (fd_to_send >= 0)
        if (ioctl(fd, I_SENDFD, fd_to_send) < 0)
        {
            printf("Eroor ::: %s\n",strerror(errno));
            return(-1);
        }
    return(0);
}




int main(int argc, char const *argv[])
{
    int fd, j, nwrite;
    char msgbuf[MSGSIZ+1];
    int fd_to_send;


    if((fd_to_send = open("vi",O_RDONLY)) < 0)
        printf("vi open failed");

    if(argc < 2)
    {
        fprintf(stderr, "Usage: sendmessage msg ... \n");
        exit(1);
    }
    /* open fifo with O_NONBLOCK set */
    if((fd = open(fifo, O_WRONLY | O_NONBLOCK)) < 0)
        printf("fifo open failed");

    /* send messages */
    for (j = 1; j < argc; j++)
    {
        if(strlen(argv[j]) > MSGSIZ)
        {
            fprintf(stderr, "message too long %s\n", argv[j]);
            continue;
        }
        strcpy(msgbuf, argv[j]);
        if((nwrite = write(fd, msgbuf, 6)) == -1)
            printf("message write failed");
    }

    printf("From send_fd %d \n",send_fd(fd,fd_to_send));

    exit(0);

}

Дополнительные файлы .h содержат только некоторые общие включаемые файлы и ничего больше. Сначала я отправляю простое сообщение, а затем вызываю send_fd, который сначала отправляет 2-байтовое сообщение, а затем должен отправить дескриптор файла с помощью ioctl. Но это не так.


person Abhishek Gupta    schedule 06.07.2012    source источник
comment
Как вы создаете файловый дескриптор? I_SENDFD — это STREAMS, и он не будет работать ни с одним каналом. Это также очень неясный API. Гораздо (намного!) чаще используется системный вызов sendmsg() для отправки файловых дескрипторов через сокеты домена Unix. Есть ли причина, по которой вы хотите использовать I_SENDFD?   -  person Andy Ross    schedule 06.07.2012
comment
Я открываю файл vi, чтобы создать дескриптор файла. Можно ли отправить дескриптор файла с помощью сообщения отправки? Я имею в виду дескриптор открытого файла, а не просто целое число.   -  person Abhishek Gupta    schedule 06.07.2012


Ответы (1)


Похоже, linux не поддерживает I_SENDFD. Комментарии указывают, что I_SENDFD есть в документации, но на самом деле не поддерживается, и приводит к сообщению об ошибке, с которым вы столкнулись. В записи в Википедии о ПОТОКАХ говорится, что ядро ​​Linux не поддерживает потоки. Запись в Википедии указывает на пару сторонних пакетов, которые можно использовать для добавления поддержки потоков, но LiS не был перенесен на ядро ​​2.6, а OpenSS7 не не было никакого активного развития в течение 4 лет.

Однако Linux поддерживает нечто подобное. Этот механизм использует специальный тип сообщения SCM_RIGHTS для доставки дескриптора файла через сокет домена UNIX с sendmsg и полученным от recvmsg. Примеры можно найти с помощью простого веб-поиска, полный пример можно найти в книге The Linux Programming Interface с источником для отправка и получение.

person jxh    schedule 06.07.2012
comment
Я не хочу отправлять дескриптор файла/дескриптор сокета, используя сокеты домена UNIX. Есть ли способ обойти. - person Abhishek Gupta; 06.07.2012
comment
@knoxxs: я сочувствую, но это немного похоже на то, что я не хочу использовать яйца для приготовления омлета. Вместо того, чтобы отправлять его в процесс, вы можете вместо этого использовать fork/exec? - person jxh; 06.07.2012
comment
Linux поддерживает I_SENDFD или, по крайней мере, документально поддерживает его. Но это странно и редко. Передача файловых дескрипторов на основе сокетов — это механизм, который все фактически используют и тестируют. - person Andy Ross; 06.07.2012
comment
@AndyRoss: Ссылка, которую я предоставил, объяснила, что это был код, который не должен был быть оставлен. Мой поиск других источников подтверждает это. - person jxh; 06.07.2012
comment
Пожалуйста, прокомментируйте отрицательный голос, чтобы я знал, что нужно улучшить, спасибо! - person jxh; 06.07.2012
comment
@knoxxs: Почему вы не хотите использовать сокеты домена UNIX? - person jxh; 06.07.2012
comment
Я хочу отправить fds двум разным процессам, у которых нет отношения родитель-потомок. Почему я хочу что-нибудь еще, только чтобы узнать (больше). Я думаю, что в Linux есть несколько способов сделать что-то. - person Abhishek Gupta; 06.07.2012
comment
@knoxxs: Это правда, но иногда это требует много работы. Если вы действительно хотите использовать потоки, вам придется портировать (и затем поддерживать) одно из сторонних дополнений к вашему ядру Linux или написать свое собственное. - person jxh; 06.07.2012