Я могу совместно использовать дескриптор файла к другому процессу на Linux, или действительно ли они локальны для процесса?

Скажите, что у меня есть 2 процесса, ProcessA и ProcessB. Если я выполняю int fd=open(somefile) в ProcessA, может я затем передавать значение дескриптора файла fd по IPC к ProcessB и это имеет, управляют тем же файлом?

50
задан nos 1 March 2010 в 10:30
поделиться

2 ответа

Вы можете передать дескриптор файла другому процессу через сокеты домена unix . Вот код для передачи такого файлового дескриптора, взятый из Сетевое программирование Unix

ssize_t
write_fd(int fd, void *ptr, size_t nbytes, int sendfd)
{
    struct msghdr   msg;
    struct iovec    iov[1];

#ifdef  HAVE_MSGHDR_MSG_CONTROL
    union {
      struct cmsghdr    cm;
      char              control[CMSG_SPACE(sizeof(int))];
    } control_un;
    struct cmsghdr  *cmptr;

    msg.msg_control = control_un.control;
    msg.msg_controllen = sizeof(control_un.control);

    cmptr = CMSG_FIRSTHDR(&msg);
    cmptr->cmsg_len = CMSG_LEN(sizeof(int));
    cmptr->cmsg_level = SOL_SOCKET;
    cmptr->cmsg_type = SCM_RIGHTS;
    *((int *) CMSG_DATA(cmptr)) = sendfd;
#else
    msg.msg_accrights = (caddr_t) &sendfd;
    msg.msg_accrightslen = sizeof(int);
#endif

    msg.msg_name = NULL;
    msg.msg_namelen = 0;

    iov[0].iov_base = ptr;
    iov[0].iov_len = nbytes;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    return(sendmsg(fd, &msg, 0));
}
/* end write_fd */

И вот код для получения дескриптора файла

ssize_t
read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
{
    struct msghdr   msg;
    struct iovec    iov[1];
    ssize_t         n;
    int             newfd;

#ifdef  HAVE_MSGHDR_MSG_CONTROL
    union {
      struct cmsghdr    cm;
      char              control[CMSG_SPACE(sizeof(int))];
    } control_un;
    struct cmsghdr  *cmptr;

    msg.msg_control = control_un.control;
    msg.msg_controllen = sizeof(control_un.control);
#else
    msg.msg_accrights = (caddr_t) &newfd;
    msg.msg_accrightslen = sizeof(int);
#endif

    msg.msg_name = NULL;
    msg.msg_namelen = 0;

    iov[0].iov_base = ptr;
    iov[0].iov_len = nbytes;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    if ( (n = recvmsg(fd, &msg, 0)) <= 0)
        return(n);

#ifdef  HAVE_MSGHDR_MSG_CONTROL
    if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
        cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
        if (cmptr->cmsg_level != SOL_SOCKET)
            err_quit("control level != SOL_SOCKET");
        if (cmptr->cmsg_type != SCM_RIGHTS)
            err_quit("control type != SCM_RIGHTS");
        *recvfd = *((int *) CMSG_DATA(cmptr));
    } else
        *recvfd = -1;       /* descriptor was not passed */
#else
/* *INDENT-OFF* */
    if (msg.msg_accrightslen == sizeof(int))
        *recvfd = newfd;
    else
        *recvfd = -1;       /* descriptor was not passed */
/* *INDENT-ON* */
#endif

    return(n);
}
/* end read_fd */
54
ответ дан 7 November 2019 в 11:05
поделиться

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

Действительно, разветвленные процессы получают все ваши FD и могут использовать их, пока не закроют их (что обычно является хорошей идеей).

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

ls -l | more

Work.

2
ответ дан 7 November 2019 в 11:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: