Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I share a file descriptor to another process on linux or are they local to the process?

Tags:

c

linux

Say I have 2 processes, ProcessA and ProcessB. If I perform int fd=open(somefile) in ProcessA, can I then pass the value of file descriptor fd over IPC to ProcessB and have it manipulate the same file?

like image 608
live2dream95 Avatar asked Mar 01 '10 20:03

live2dream95


People also ask

Can file descriptors be shared between processes?

File descriptors are generally unique to each process, but they can be shared by child processes created with a fork subroutine or copied by the fcntl, dup, and dup2 subroutines.

Does each process have its own file descriptor table?

The file descriptor table itself contains pointers to the file objects which do all the resource handling. Each process (a process being an instance of an application) has it's own file descriptor table which is pointed to by an entry in it's process description table.

How does Linux file descriptor work?

A file descriptor is a number that uniquely identifies an open file in a computer's operating system. It describes a data resource, and how that resource may be accessed. When a program asks to open a file — or another data resource, like a network socket — the kernel: Grants access.

Can two file descriptors point to the same file?

Pointers to the Open File Table: One process can have multiple file descriptors point to the same entry (e.g., as a result of a call to dup() ) Multiple processes (e.g., a parent and child) can have file descriptors that point to the same entry.


1 Answers

You can pass a file descriptor to another process over unix domain sockets. Here's the code to pass such a file descriptor, taken from Unix Network Programming

ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd) {     struct msghdr   msg;     struct iovec    iov[1];  #ifdef  HAVE_MSGHDR_MSG_CONTROL     union {       struct cmsghdr    cm;       char              control[CMSG_SPACE(sizeof(int))];     } control_un;     struct cmsghdr  *cmptr;      msg.msg_control = control_un.control;     msg.msg_controllen = sizeof(control_un.control);      cmptr = CMSG_FIRSTHDR(&msg);     cmptr->cmsg_len = CMSG_LEN(sizeof(int));     cmptr->cmsg_level = SOL_SOCKET;     cmptr->cmsg_type = SCM_RIGHTS;     *((int *) CMSG_DATA(cmptr)) = sendfd; #else     msg.msg_accrights = (caddr_t) &sendfd;     msg.msg_accrightslen = sizeof(int); #endif      msg.msg_name = NULL;     msg.msg_namelen = 0;      iov[0].iov_base = ptr;     iov[0].iov_len = nbytes;     msg.msg_iov = iov;     msg.msg_iovlen = 1;      return(sendmsg(fd, &msg, 0)); } /* end write_fd */ 

And here's the code to receive the file descriptor

ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd) {     struct msghdr   msg;     struct iovec    iov[1];     ssize_t         n;     int             newfd;  #ifdef  HAVE_MSGHDR_MSG_CONTROL     union {       struct cmsghdr    cm;       char              control[CMSG_SPACE(sizeof(int))];     } control_un;     struct cmsghdr  *cmptr;      msg.msg_control = control_un.control;     msg.msg_controllen = sizeof(control_un.control); #else     msg.msg_accrights = (caddr_t) &newfd;     msg.msg_accrightslen = sizeof(int); #endif      msg.msg_name = NULL;     msg.msg_namelen = 0;      iov[0].iov_base = ptr;     iov[0].iov_len = nbytes;     msg.msg_iov = iov;     msg.msg_iovlen = 1;      if ( (n = recvmsg(fd, &msg, 0)) <= 0)         return(n);  #ifdef  HAVE_MSGHDR_MSG_CONTROL     if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&         cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {         if (cmptr->cmsg_level != SOL_SOCKET)             err_quit("control level != SOL_SOCKET");         if (cmptr->cmsg_type != SCM_RIGHTS)             err_quit("control type != SCM_RIGHTS");         *recvfd = *((int *) CMSG_DATA(cmptr));     } else         *recvfd = -1;       /* descriptor was not passed */ #else /* *INDENT-OFF* */     if (msg.msg_accrightslen == sizeof(int))         *recvfd = newfd;     else         *recvfd = -1;       /* descriptor was not passed */ /* *INDENT-ON* */ #endif      return(n); } /* end read_fd */ 
like image 125
nos Avatar answered Sep 28 '22 06:09

nos