Sie können keinen Socket (oder einen anderen Dateideskriptor) über den gemeinsamen Speicher von einem Prozess zum anderen übertragen. Ein Dateideskriptor ist nur eine kleine Ganzzahl. Wenn Sie diese Ganzzahl im gemeinsam genutzten Speicher ablegen und von einem anderen Prozess darauf zugreifen, wird aus der Sicht des anderen Prozesses nicht automatisch dieselbe Ganzzahl zu einem gültigen Dateideskriptor.
Die korrekte Methode zum Senden eines Dateideskriptors von einem Prozess zu einem anderen besteht darin, ihn als SCM_RIGHTS
Zusatzdaten mit sendmsg()
über einen vorhandenen Socket-Kommunikationskanal zwischen den beiden Prozessen zu senden.
Zuerst erstellen Sie Ihren Kommunikationskanal mit socketpair()
vor Ihnen fork()
. Schließen Sie jetzt im übergeordneten Element ein Ende des Sockelpaars, und schließen Sie das andere Ende im untergeordneten Element. Sie können jetzt sendmsg()
von dem Elternteil an einem Ende dieses Sockets und mit recvmsg()
im Kind mit dem anderen Ende empfangen.
eine Nachricht mit SCM_RIGHTS
Senden sieht wie folgt aus etwas:
struct msghdr m;
struct cmsghdr *cm;
struct iovec iov;
char buf[CMSG_SPACE(sizeof(int))];
char dummy[2];
memset(&m, 0, sizeof(m));
m.msg_controllen = CMSG_SPACE(sizeof(int));
m.msg_control = &buf;
memset(m.msg_control, 0, m.msg_controllen);
cm = CMSG_FIRSTHDR(&m);
cm->cmsg_level = SOL_SOCKET;
cm->cmsg_type = SCM_RIGHTS;
cm->cmsg_len = CMSG_LEN(sizeof(int));
*((int *)CMSG_DATA(cm)) = your_file_descriptor_to_send;
m.msg_iov = &iov;
m.msg_iovlen = 1;
iov.iov_base = dummy;
iov.iov_len = 1;
dummy[0] = 0; /* doesn't matter what data we send */
sendmsg(fd, &m, 0);
eine Nachricht mit SCM_RIGHTS
Empfangen darin etwas geht:
struct msghdr m;
struct cmsghdr *cm;
struct iovec iov;
struct dummy[100];
char buf[CMSG_SPACE(sizeof(int))];
ssize_t readlen;
int *fdlist;
iov.iov_base = dummy;
iov.iov_len = sizeof(dummy);
memset(&m, 0, sizeof(m));
m.msg_iov = &iov;
m.msg_iovlen = 1;
m.msg_controllen = CMSG_SPACE(sizeof(int));
m.msg_control = buf;
readlen = recvmsg(fd, &m, 0);
/* Do your error handling here in case recvmsg fails */
received_file_descriptor = -1; /* Default: none was received */
for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) {
if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) {
nfds = (cm->cmsg_len - CMSG_LEN(0))/sizeof(int);
fdlist = (int *)CMSG_DATA(cm);
received_file_descriptor = *fdlist;
break;
}
}
Ich habe über Eltern/Kind-Prozess gesprochen, so ist die Frage: Wie Kind Zugriff auf Datei-Deskriptor von dem Elternteil nach einer Gabel gemacht? – user1995143
+1 Für eine nette Antwort, aber es klingt für mich, als wäre er besser dran mit Threads. –
@ user1995143 Das ist genau die Frage, die ich beantwortet habe. Es spielt keine Rolle, was die Eltern-Kind-Beziehung der beiden Prozesse ist. Solange Sie einen UNIX-Domain-Socket als Kommunikationskanal haben, können Sie mit dieser Technik Dateideskriptoren übertragen. Oder Sie können dem Vorschlag von [Robert S. Barnes] (http://stackoverflow.com/users/71074/robert-s-barnes) folgen und mehrere Threads anstelle von mehreren Prozessen verwenden. Dann müssen Sie sich keine Gedanken darüber machen, da Dateideskriptoren von allen Threads eines einzelnen Prozesses gemeinsam genutzt werden. – Celada