Совместное использование дескриптора файла между родителем и предварительно разветвленными детьми - PullRequest
1 голос
/ 21 февраля 2010

В сетевом программировании Unix есть пример предварительно разветвленного сервера, который использует передачу сообщений по доменному каналу Unix для указания дочерним процессам обработки входящего соединения:

for ( ; ; ) {
    rset = masterset;
    if (navail <= 0)
        FD_CLR(listenfd, &rset);    /* turn off if no available children */
    nsel = Select(maxfd + 1, &rset, NULL, NULL, NULL);

        /* 4check for new connections */
    if (FD_ISSET(listenfd, &rset)) {
        clilen = addrlen;
        connfd = Accept(listenfd, cliaddr, &clilen);

        for (i = 0; i < nchildren; i++)
            if (cptr[i].child_status == 0)
                break;              /* available */

        if (i == nchildren)
            err_quit("no available children");
        cptr[i].child_status = 1;   /* mark child as busy */
        cptr[i].child_count++;
        navail--;

        n = Write_fd(cptr[i].child_pipefd, "", 1, connfd);
        Close(connfd);
        if (--nsel == 0)
            continue;   /* all done with select() results */
}

Как видите, родительский файл записывает номер дескриптора файла для сокета в канал, а затем вызывает close для дескриптора файла. Когда преформированные потомки заканчивают работу с сокетом, они также вызывают close в дескрипторе. То, что бросает меня в тупик, заключается в том, что, поскольку эти дочерние элементы предварительно разветвляются, я предполагаю, что только те файловые дескрипторы, которые существовали в то время, когда дочерние элементы были разветвлены, будут доступны совместно. Однако, если бы это было правдой, то этот пример эффектно провалился бы, но все же он работает.

Может ли кто-нибудь пролить свет на то, как дескрипторы файлов, созданные родительским после того, как разветвление в конечном итоге стало доступно процессу потомков?

Ответы [ 2 ]

5 голосов
/ 21 февраля 2010

Посмотрите на реализацию Write_fd. Он использует что-то вроде

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;

То есть отправка управляющего сообщения с типом SCM_RIGHTS - это способ, которым unixes может совместно использовать файловый дескриптор с не связанным процессом.

1 голос
/ 23 февраля 2010

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

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

Большинство серверов prefork НЕ делают этого, скорее, они имеют дочерний вызов процесса accept () в общем сокете прослушивания и таким образом создают свой собственный подключенный сокет. Другие процессы не могут видеть этот подключенный сокет, и существует только одна его копия, поэтому, когда дочерний объект закрывает его, он исчезает.

Один недостаток состоит в том, что процесс не может сказать, что клиент собирается запросить, ДО того, как он вызовет accept, поэтому вы не можете обрабатывать разные типы запросов у разных дочерних элементов и т. Д. Как только один дочерний объект принимает () его, другой дочерний элемент не может.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...