views:

88

answers:

2

When we want to pass a descriptor from child to process, UNP V1(Unix network programming V1) specifies a complex procedure of doing this, first to create msghdr struct and then something, etc.

Why cant we pass a descriptor as normal data means as we do send , recv for other data through unix domain sockets? I am able to understand the process. Please explain the method given in that book.

Also, in that book, in read_fd() function, he declares the union to properly align the msghdr struct. How union makes it aligned? and why alignment is required?

A: 

Without having a copy of that book, it's going to be difficult for us to explain to you the method given in the book.

There are several general techniques to pass a file descriptor from a parent process to a child process. If you know the file descriptor number before launching the child:

  • put it in a command line parameter
  • put it in an environment variable
  • put it in a file on disk (not a great option)

If you only know the file descriptor after launching the child, then some sort of IPC will be needed:

  • put it in shared memory
  • send it to the child on a socket

It sounds like the book you're reading describes the last option. When sending a message to a child, you are free to choose the representation of whatever data you are sending. If you're sending a file descriptor (an integer) and no other information, then you're free to choose pretty much any representation. An ASCII representation of the integer might be suitable, or you could send four bytes representing a 32-bit integer.

Again, it's hard to guess why the book author is doing things the way they are, without knowing what the method actually is.

Greg Hewgill
+2  A: 

Why cant we pass a descriptor as normal data means as we do send , recv for other data through unix domain sockets?

Because an open file descriptor is not usefully serializable as a stream of bytes.

While file descriptors are actually just integers, they are mapped by the kernel (in a per-process manner) to kernel-internal data structures that describe the details of the opened ‘file’ (is it ‘normal’ file? is is a block/character special device? is it a network socket of some sort? is it anonymous pipe? etc.). The goal of file descriptor passing is to create a new file descriptor (probably with some other integer value) in some other (possibly unrelated) process that is mapped to the same kernel-internal data structure as the original descriptor in the sending process.

The machinations you have to go through to do this are just the “API” to access this functionality (note that System V based Unix systems have an alternate method of file descriptor passing based on STREAMS, which uses a different “API”). I do not know the history, but I would guess that the “complexity” of the BSD file descriptor passing “API” is due to shoehorning the functionality into the preexisting sendmsg(2)/recvmsg(2) API.

How union makes it aligned? and why alignment is required?

I do not have the UNP implementation in front of me, but using a union is not the only way to go. Kragen Sitaker's portlisten example uses the CMSG_* macros instead of a union. The idea is to make sure that <struct msghdr>.msg_control points to the <struct cmsghdr>.

Chris Johnsen