Nowe posty

Autor Wątek: Procesy- wymiana deskryptorów  (Przeczytany 4238 razy)

Ksanderon

  • Gość
Procesy- wymiana deskryptorów
« dnia: 2012-02-09, 00:04:25 »
czy istnieje jakakolwiek możliwość (przy użyciu mmap, shm etc...) przekazywania otwartego deskryptora pliku pomiędzy procesami tak aby w obu był "otwarty"?
Jak?

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3066
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Procesy- wymiana deskryptorów
« Odpowiedź #1 dnia: 2012-02-09, 08:01:31 »
Deskryptory są indeksami w tabeli otwartych plików będących częścią struktury opisującej proces. Po przekazaniu ich do drugiego procesu nie maja sensu, bo pokazują na pliki procesu "odbiorcy" a nie "nadawcy".

Potrzebujesz mechanizmu, który - siedząc ponad obydwoma procesami - zrobi dup(2) z jednego do drugiego.

Pierwsze mruki na ten temat były koło roku 2000 - wykorzystują gniazda UNIXa i msgsend z odpowiednim parametrem. Znalazłem takie (niezweryfikowane) przykłady:

NADAWCA:
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 */
ODBIORCA:

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 */
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy

Ksanderon

  • Gość
Procesy- wymiana deskryptorów
« Odpowiedź #2 dnia: 2012-02-09, 14:04:00 »
masz może jakieś info na ten temat- poczytałbym sobie.

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3066
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Procesy- wymiana deskryptorów
« Odpowiedź #3 dnia: 2012-02-09, 22:18:59 »
Poszukaj w Google o SCM_RIGHTS i descriptor sharing. Jest trochę o tym w sieci, nawet jakieś man-y się trafiają.
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy

Ksanderon

  • Gość
Procesy- wymiana deskryptorów
« Odpowiedź #4 dnia: 2012-02-10, 10:46:52 »
dzięki. po przeczytaniu manpage http://manpages.ubuntu.com/manpages/dapper/pl/man7/unix.7.html wygląda to dosyć znośnie. Napisałem sobie programik testowy otwierający socket w matce po forku, piszący do niego w dziecku- zdaje się, że działa, zacznę pisać praktyczny kod.

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3066
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Procesy- wymiana deskryptorów
« Odpowiedź #5 dnia: 2012-02-10, 13:16:43 »
Z czystej ciekawości - po grzyba takie "nieczyste" rozwiązanie? Jedyny scenariusz, jaki widzę dla przekazywania PIDów to serwer wieloprocesowy (zamiast wielowątkowego):
- proces rodzic powołuje do życia pulę procesów-potomków
- wpada w pętlę accept-a (więc nie można przekazać uchwytów w fazie "rodzenia" potomków)
- po przyjęciu zgłoszenia (uchwyt gniazda zwrócony z accept) przekazuje go do kogoś z puli.

Zgadłem?
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy

Ksanderon

  • Gość
Procesy- wymiana deskryptorów
« Odpowiedź #6 dnia: 2012-02-10, 13:43:18 »
dokładnie:) zastanawiałem się czy takie coś jest możliwe.

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3066
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Procesy- wymiana deskryptorów
« Odpowiedź #7 dnia: 2012-02-10, 22:30:23 »
Jest możliwe i nawet stosowane w systemach HA.

1) Totalna zwałka procesu z puli nie ma wpływu na resztę. W przypadku wątków jest duże prawdopodobieństwo, że cały proces pójdzie w pi*ę.
2) Przy rozsądnym zarządzaniu można dynamicznie powoływać i zabijać procesy w puli działające na niższych uprawnieniach niż proces centralny.

Co waćpan kombinujesz, jeżeli to nie tajemnica?

P.S. Jeżeli potrzebujesz takich zabaw, to popatrz na język Erlang. Wydaje się wprost stworzony do Twojego zagadnienia. Jeżeli jesteś z Wawy, to 28 lutego koło 16:30 w laboratorium Brama na PW będę prowadził wieczorek zapoznawczy z Erlangiem.
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy

Ksanderon

  • Gość
Procesy- wymiana deskryptorów
« Odpowiedź #8 dnia: 2012-02-13, 21:48:27 »
Nie nie tajemnica- staram się jak coś robię to robić przynajmniej zadowalająco a zabawy z przeróżnymi serwerami to takie moje "hobby". Jako, że zwykle moje popełnienia to tu to tam chcąc-nie chcąc korzystają z klient-serwer("bo to takie fajne jest"), mam ku temu gotowe uniwersalne szabloniki, remedium na wszelkie problemy "tamtego" świata( :) ), które gdy coś sensownego przyjdzie mi do głowy staram się udoskonalić, ażeby przy konkretnym już projekcie nie było zbytnich problemów z implementacją.

Ostatnio zauważyłem mniej więcej to co stwierdziłeś w 1) i zaczęło mnie zastanawiać co z tym fantem można począć. Tak ot dotarłem, do jak widać niezbyt odkrywczego rozwiązania: oddzielmy w serwerze część "niezbędnie konieczną/niezniszczalną" od reszty tałatajstwa przy pomocy procesów.

PS. Już żałuję, że nie wybrałem się na PW, choć na PWr też jest fajnie :)

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3066
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Procesy- wymiana deskryptorów
« Odpowiedź #9 dnia: 2012-02-14, 15:45:51 »
Ja akurat na PW jestem tylko gościnnie - sam jestem po PSzcz (póki tak się jeszcze nazywała). Na jeden LwB wpadłem zainteresowany wykładem o CUDA a na następnym byłem już z własnym odczytem :)
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy