Comment sendmsg œuvres?
Comme vous le savez sendmsg a cette déclaration:
int sendmsg(int s, const struct msghdr *msg, int flags);
et msghdr structure a cette forme:
struct msghdr {
void * msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec * msg_iov; /* scatter/gather array */
size_t msg_iovlen; /* # elements in msg_iov */
void * msg_control; /* ancillary data, see below */
socklen_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
Comme vous le voyez msghdr a un tableau de tampon, iovec et a tampons msg_iovlen. Ce que je me demande, c'est que la façon dont sendmsg envoie ces tampons. Est-il concaténer tous les tampons et d'envoyer ou de ne l'envoyer dans une boucle for?
Juste une remarque: si c'est pour la curiosité, puis laisser refroidir. Si vous essayez d'écrire quelque chose qui dépend de cette connaissance, alors vous êtes presque certainement de faire le mal et d'avoir des ennuis.
il serait utile pour vous de donner des précisions sur pourquoi écrire quelque chose qui dépend de cette connaissance est d'avoir des ennuis. Êtes-vous en mesure d'élaborer s'il vous plaît?
Parce que la documentation vous propose un ensemble de code interfaces et vous dit à quoi s'attendre de leur part. Les interfaces sont très lentes à changer. Le code sous-jacent n'a pas une telle garantie. Si vous êtes à glaner des connaissances de l'intérieur et de l'écriture de votre code autour de cette connaissance, alors vous ne devriez pas être surpris si vous mettez à jour votre noyau ou des pilote sur la pile de réseau et de votre code qui l'appelle, il ne fonctionne plus. Vous avez fait un mauvais choix si vous n'avez ce.
il serait utile pour vous de donner des précisions sur pourquoi écrire quelque chose qui dépend de cette connaissance est d'avoir des ennuis. Êtes-vous en mesure d'élaborer s'il vous plaît?
Parce que la documentation vous propose un ensemble de code interfaces et vous dit à quoi s'attendre de leur part. Les interfaces sont très lentes à changer. Le code sous-jacent n'a pas une telle garantie. Si vous êtes à glaner des connaissances de l'intérieur et de l'écriture de votre code autour de cette connaissance, alors vous ne devriez pas être surpris si vous mettez à jour votre noyau ou des pilote sur la pile de réseau et de votre code qui l'appelle, il ne fonctionne plus. Vous avez fait un mauvais choix si vous n'avez ce.
OriginalL'auteur whoi | 2010-11-23
Vous devez vous connecter pour publier un commentaire.
La page de manuel parle d'un message (au singulier), et de multiples éléments (au pluriel):
Pour un socket de flux, il ne serait pas question de toute façon. Toutes les données que vous envoyez viens de finir comme un long flux de données sur l'autre côté.
Pour datagramme ou message sockets, je peux voir pourquoi un peu plus de clarté serait utile. Mais il semble que vous simplement envoyer un datagramme ou un message avec un seul
sndmsg
appel; pas un pour tampon élément.Je suis allé creuser dans le code source de Linux par curiosité et pour obtenir un meilleur sentiment au sujet de cette réponse. Il ressemble à
send
, etsendto
sont juste des wrappers poursendmsg
dans Linux, qui construisent lastruct msghdr
pour vous. Et en fait, l'UDPsendmsg
mise en œuvre fait de la place pour un entête UDP parsendmsg
appel.Si la performance est ce que vous êtes inquiet au sujet, il ne semble pas que vous allez bénéficier de
sendmsg
si vous passez en un seuliovec
. Si vous êtes à la concaténation de tampons dans l'espace utilisateur, cependant, cela pourrait vous faire gagner quelques.C'est un peu similaire à
writev
, avec l'avantage supplémentaire que vous pouvez spécifier une adresse de destination pour une utilisation sans connexion avec les sockets comme UDP. Vous pouvez également ajouter des données auxiliaires, si vous êtes dans ce genre de chose. (Couramment utilisé pour envoyer des descripteurs de fichiers à travers des sockets de domaine UNIX.)"Si le message est trop long pour être transmis intégralement par le protocole, l'erreur EMSGSIZE est retourné, et le message n'est pas transmis." (linux.die.net/man/2/sendmsg) - n'est-ce pas la spécification exacte de ce que linux n'en UDP/paquet sockets ("atomiquement"!)? Ou l'inverse, si linux a fait quelque chose de différent, ne serait-il pas échouer le cahier des charges?
Je pense que vous êtes en train de regarder quelque chose de différent. Le
iovec
genre de choses est à propos de la concaténation d'un tas de tampons et de les envoyer en un seul message.EMSGSIZE
est quelque chose qui pourrait se produire après le traitement, si le total de votre message dépasse un certain protocole de limite.Pensez-vous donc? Vous avez trouvé par le code 'creuser' que linux se réserve un en-tête UDP par sendmsg d'appel et j'ai remis la raison pour laquelle il n' - parce que requis par la norme...
D'autre part si la question est vraiment pour les OS internes, ninjalj la réponse est peut-être plus approprié pour cette question...
OriginalL'auteur Stéphan Kochen
Cela dépend de votre pile TCP/IP. Incorporé des piles TCP/IP peut potentiellement envoyer les différents iovecs directement à la carte réseau. Mais d'habitude des piles TCP/IP il faut déjà être une copie à partir de l'espace utilisateur de la mémoire à kernelspace de mémoire, donc il n'y a pas de gain, et iovecs obtenir sur le plan conceptuel copiés dans un seul gros morceau de la mémoire (il peut être distinct des pages de la mémoire, si le pilote prend en charge scather/recueillir des I/O, mais l'important est ici que iovec limites à ne pas être préservé).
OriginalL'auteur ninjalj
Selon http://opengroup.org/onlinepubs/007908799/xns/sendmsg.html ...
Mon interprétation est quesendmsg()
ne sera pas concaténer le message de données stockées dans le iovec; chacun de vous sera envoyé dans un message séparé.[Modifier: Mon interprétation n'est pas correcte; voir les autres réponses pour une meilleure explication.]
proto_ops->sendmsg()
...et, en particulier, si vous utilisez
sendmsg()
sur unSOCK_DGRAM
socket, vous obtiendrez datagramme avec les données de tous les iovecs.Je suis corrigé, merci pour la clarification.
OriginalL'auteur Kamal