UNIX Domain sockets introduction UNIX domain sockets are used to communicate between processes running on the same machine. Although Internet domain sockets can be used for the same purpose, UNIX domain sockets are more efficient.
UNIX domain sockets only replicate data, they do not perform protocol processing, do not need to add and remove network headers, do not have to calculate the inspection and, do not produce sequential numbers, do not need to send acknowledgement messages. UNIX domain sockets provide both stream and datagram interfaces. The UNIX domain datagram service is reliable and does not lose messages or pass errors. A UNIX domain socket is a mixture of sockets and pipelines. To create a pair of non-named, interconnected UNIX domain sockets, users can use their network-oriented domain sockets interface or use the Socketpair function.
#include <sys/types.h> #include <sys/socket.h>int socketpair (int domain, int type, int protocol, int SOCKFD[2]);
Note: The non-named pipe created here is a full-duplex pipeline, where two descriptors can be used for both reading and writing, respectively. The following is an example of the function used:
int fd[2];p id_t pid;socketpair (Af_unix, Socket_stream, 0, FD);//Create pipeline if (PID = fork ()) = = 0) {//Sub-process close (fd[0]);// Close the parent process side of the pipe dup2 (fd[1], Stdout_fileno);//Sub-process end of the replication pipeline to standard output dup2 (fd[1], Stdin_fileno);//Sub-process end of the replication pipeline to standard input Close (fd[1]);//Turn off replicated read Pipelines/ * use EXEC to execute commands */} else {//parent process close (fd[1]);//close pipeline sub-process Side/ * Now read/write data in fd[0] */ shutdown (fd[0], SHUT_WR);//notify End data Sent/ * Read remaining data * /Close (fd[0]);//close pipe/ * Use the Wait series function to wait for the child process to exit and get the exit code */}
Transferring file descriptors Unix domain sockets a very important use is to transfer file descriptors between processes. The ability to transfer open file descriptors between processes is very useful and can be used to design different applications for client/server processes. It enables a process (typically a server process) to handle everything required to open a file and send a descriptor back to the calling process, which used by itself is used for all future I/O functions. All details that involve opening a file or device are hidden from the client process.When
a process transmits an open file descriptor to another process, it actually wants to send the process and accept the process to share the same file table entry。 Technically, the sending process actually sends a pointer to the receiving process that points to an open File table entry. The pointer is assigned to the first available descriptor item in the receiving process. (Note that it is not an illusion to assume that the descriptor numbers in the sending process and the receiving process are the same, usually they are different). Two processes share the same Open File table entry, at which point the parent, child process shares open a file table entry exactly as it was after the fork. When the sending process describes nginx to the acceptance process, it usually closes the descriptor. Sending a process to close the descriptor does not cause the file or device to be closed, because the file corresponding to the descriptor is still considered open by the accepting process (even if the acceptance process has not yet accepted the descriptor). In order to swap file descriptors with UNIX domain sockets, call sendmsg and recvmsg. The parameters of both functions have a pointer to the MSGHDR structure that contains all the information about sending and receiving content. The structure is defined as follows:
struct MSGHDR { void *msg_name; int Msg_namelen; struct Iovec *msg_iov; __kernel_size_t Msg_iovlen; void *msg_control; __kernel_size_t Msg_controllen; unsigned msg_flags; };
Where the first two elements are typically used to send data packets over a network connection, where the destination address can be specified by each data message. The following two elements allow us to specify an array consisting of multiple buffers (scatter-read and aggregate-write). The Msg_flags field contains a flag that describes the message that is received. Two elements handle the transmission and reception of control messages. The Msg_control field points to the CMSGHDR (control information header) structure, and the Msg_controllen field contains the number of bytes of control information.
struct CMSGHDR { socklen_t cmsg_len; /* Data byte count, including header */ int cmsg_level; /* Originating protocol */ int cmsg_type; /* protocol-specific Type */ * followed by unsigned char cmsg_data[]; */ };
In order to send the file descriptor, set Cmsg_len to the length of the CMSGGHDR structure plus an integer (descriptor) length, cmsg_level field set to Sol_socket,cmsg_type field set to Scm_rights, To indicate that we are transmitting access rights. (SCM refers to the socket-level control message, which is the socket_level. Access can only be transmitted via UNIX domain sockets. The descriptor is placed immediately after the Cmsg_type field, and a pointer to the integer quantity is obtained with the Cmsg_data macro.