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>
.