Powiedz, że mam 2 procesy, ProcessA i ProcessB. Jeśli wykonuję int fd=open(somefile)
w ProcessA, czy mogę przekazać wartość deskryptora pliku fd
przez IPC do ProcessB i zmusić go do manipulowania tym samym plikiem?Czy mogę udostępnić deskryptor pliku innemu procesowi na Linuksie lub czy jest on lokalny w procesie?
Odpowiedz
Możesz przekazać deskryptor pliku do innego procesu przez gniazda unix domain. Oto kod przekazać taką deskryptor pliku, zaczerpnięte z Unix Network Programming
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 */
A oto kod aby otrzymać deskryptor
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 */
Należy jednak zauważyć, że rzeczywista wartość liczbowa deskryptora pliku będzie na ogół różna w obu procesach. – caf
Możesz przekazać * * w ten sposób. Nie oznacza to jednak, że będzie działać jako deskryptor pliku dla tego samego pliku po obu stronach. – EJP
@EJP Pomysł z SCM_RIGHTS jest taki, że będzie. Chociaż nikt nie przychodzi mi do głowy, jestem pewien, że są pewne zastrzeżenia. (tzn. koncepcja działa prawie jak dup(), ale między niezwiązanymi procesami) – nos
Można użyć NOS metoda opisana w tym wątku, albo (bardziej konwencjonalny) sposób, dzieląc go między powiązanymi procesami (zazwyczaj rodzic-dziecko lub rodzeństwo) poprzez jego utworzenie, rozwidlone procesy automatycznie otrzymują kopię.
Rzeczywiście, procesy rozwidlone pobierają wszystkie twoje dyski FD i mogą z nich korzystać, chyba że je zamkną (co jest generalnie dobrym pomysłem).
Dlatego jeśli rodzic wyświetli dwoje dzieci, jeśli oba mają deskryptor pliku, który nie został zamknięty, jest on udostępniany (nawet jeśli rodzic następnie je zamknie). Może to być na przykład fajka z jednego dziecka na drugie. W ten sposób powłoka przekierowuje, jak
ls -l | more
.
Należy zauważyć, że w przykładzie powyżej, ustawienie zmiennych przy odbiorze, jak:
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;
nie jest wymagane. Cała idea struktury wiadomości z nagłówkami polega na tym, że strona odbierająca nie musi wiedzieć, co czyta, i może poprzez sprawdzenie (pierwszego) nagłówka, jakiego rodzaju wiadomości jest i czego się spodziewać.
Chociaż technicznie poprawne, istnieje dobry powód, aby określić bufor w tym przypadku: w celu wysłania wiadomości OOB (komunikat kontrolny gniazda w tym przypadku), musisz podać niepusty komunikat (zobacz unix_stream_sendmsg, np. http://lxr.free-electrons.com/source/net/unix/af_unix.c#L1836). Podczas odbierania bez iovec, Linux będzie dostarczał tę wiadomość w kółko. Dlatego, aby przeczytać więcej niż jedną wiadomość OOB, MUSISZ przeczytać dane wiadomości w pewnym momencie. – Michael
Jeśli oba procesy należą do tego samego użytkownika, można po prostu skorzystać z procfs.
char fd_path[64]; // actual maximal length: 37 for 64bit systems
snprintf(fd_path, sizeof(fd_path), "/proc/%d/fd/%d", SOURCE_PID, SOURCE_FD);
int new_fd = open(fd_path, O_RDWR);
Oczywiście potrzebny jest jakiś mechanizm IPC, aby udostępnić wartość SOURCE_FD
. Zobacz np. "Linux C: upon receiving a signal, is it possible to know the PID of the sender?".
- 1. deskryptor gniazda vs deskryptor pliku
- 2. Czy jest on niezawodny?
- 3. Czy mogę powtórzyć deskryptor formatu napisów w pythonie?
- 4. Czy można skompilować VST na Linuksie?
- 5. Odzyskiwanie deskryptor pliku z std :: fstream
- 6. Czy można wyłączyć setlocale() w procesie?
- 7. Co to jest użycie deskryptora pliku 255 w procesie bash
- 8. PHP: jak sprawdzić, czy klient jest lokalny?
- 9. Czy Visual Basic jest obsługiwany przez .NET Core na Linuksie?
- 10. Nie można uzyskać dostępu do pliku, ponieważ jest on używany w innym procesie.
- 11. Jaki jest pożytek z fd (deskryptor pliku) w węźle js
- 12. Czy naprawdę konieczne jest zamknięcie nieużywanego końca rury w procesie
- 13. Czy mogę zapobiec blokowaniu pliku tekstowego przez StreamReader, gdy jest on używany?
- 14. Czy mogę udostępnić publiczny interfejs API rozpoznawania mowy offline Androidowi?
- 15. Atomowe zapisywanie do pliku na Linuksie
- 16. Czy można sprawdzić, czy WSAStartup został wywołany w procesie?
- 17. Czy mogę udostępnić moje prywatne repozytorium GitHub przez link?
- 18. Czy można bezpiecznie udostępnić publicznie Firebase apiKey?
- 19. Zapobieganie procesowi "proces jest zły" błędu
- 20. Czy mogę wybrać() na deskryptorze pliku/dev/spidev?
- 21. Czy kolejki wiadomości są przestarzałe w Linuksie?
- 22. Na Linuksie, czy mogę uzyskać klucze do zachowania się w inny sposób, jeśli dotknąłem?
- 23. Jak uzyskać deskryptor pliku bufora w pamięci?
- 24. Czy jest jakieś zdarzenie "on DOM change"?
- 25. wywołanie systemowe do odwzorowania pamięci na deskryptor pliku (odwrotność mmap)?
- 26. Czy/tmp w Linuksie kiedykolwiek się zapełnia?
- 27. Kopiowanie pliku z HDFS na lokalny komputer
- 28. Czy mogę utworzyć moduł lokalny z menedżerem pakietów Swift?
- 29. Bad deskryptor pliku - Heroku Foreman
- 30. Używanie NSPredicate do określenia, czy ciąg znaków jest równy innemu ciągowi znaków
Duplikat: http://stackoverflow.com/questions/1997622 – Zitrax
Zobacz [to pytanie] (http://stackoverflow.com/questions/1997622). – bmargulies