|
Blue Forest http://www.lslnet.com at 10:18 on June 6, 2006
Inter-Process Communication in Unix
[code]
Inter-Process Communication in Unix
Pipes
Include Files :
#include "Unistd.h>;
#include "Sys/types.h>;
#include "Sys/stat.h>;
#include "Sys/time.h>;
#include "Sys/mman.h>;
#include "Sys/un.h>;
#include "Netinet/in.h>;
#include "Netdb.h>;
#include "Socket.h>;
Int pipe (int filedes[2]);
Opens : filedes[0] two file descriptors will be open for reading. filedes[1] and will be open for writing. Filedes[0] will read what is written into filedes[1]. This is a mechanism for communication between a parent process to its inter-process child :
Int n, fd[2];
Pid_t pid;
Char line[1024];
Int main (void)
{
If (pipe (fd) "0)
(Perror ( "pipe"); Exit (1); )
If ((pid = fork ()) "0)
(Perror ( "fork"); Exit (1); )
Else if (pid "; 0) (
Close (fd[0]);
Write (fd[1] "world\n Panorama," 12);
While (wait (null) "0);
) Else (
Close (fd[1]);
N = read (fd[0], line, 1024);
Write (STDOUT_FILENO, line, n);
}
Exit (0);
}
In a production code read () and write () should also be checked for errors.
Fifos
Int mkfifo (const char *pathname, mode_t mode);
Creates a file of type fifo, or named pipe. After the file is created, it can be accessed using the usual open (), read () and write (). close (), unlink () and so forth.
Opening a fifo for reading will block until someone else has opened the fifo for writing. unless the fifo is opened with the O_NONBLOCK option (in the second argument of the open () system call).
Fifos are similar to pipes but can be used without a parent-child relationship between processes. Here is an example of using fifos from the shell. Both need the output from prog1 prog2 and prog3. and we do 't want to use a temporary file. So we write :
Mkfifo fifo1
Prog3 "fifo1 &
Prog1 "input_file | | prog2 Mo'tee fifo1
Select
Int select (int maxfdp1, fd_set *readfds, fd_set *writefds.
Fd_set *execptfds, struct timeval *tvptr);
Waits for an event to occur in one of many I/O file descriptors. You can wait until they are ready for reading, ready for writing. or an exception occurred at them. The first argument is the maximum number of file descriptors that are in any of the sets plus 1. The tvptr argument specifies the maximum time to wait (can be 0.0 seconds as well). or can be NULL. If it 's NULL, we wait until one of the descriptors is ready or until we get a signal.
The function returns -1 on error. or the number of ready file descriptors (0 if we can be timed out). If the process receives a signal while in select (). the function returns with 1 and sets errno to EINTR. Therefore, many times signals are blocked during select ().
(Struct timeval
Long tv_sec; LEAVES OF 13 SPECIES OF LAURACEAE seconds */
Long_tv_usec; LEAVES OF 13 SPECIES OF LAURACEAE microseconds */
}
This is the time structure used by select () and many other routines that handle time. Most system clocks are accurate to the level of 10-50 microseconds.
FD_ZERO (fd_set *fdset);
FD_SET (int fd, fd_set *fdset);
FD_CLR (int fd, fd_set *fdset);
FD_ISSET (int fd, fd_set *fdset);
These functions manupulate the "file descriptor set" data type used for three of the five arguments of the select system call. They allow initializing. adding to, checking and removing from membership of a set.
Memory Mapped Files
Caddr_t mmap (caddr_t addr, size_t entrants, int proteges, int flag.
Int filedes, off_t off);
Maps a file into memory. 'Filedes' is the descriptor of the file to map; the file must be open. however un-map it will not closing it later. 'addr' is the address in memory to map to-0 as it is recommended to pass this argument to let the system decide. 'off' is the offset in the file from which to map; 'entrants' is the number of bytes to map. starting from that offset. 'proteges' is the protection mode for the mapped file-it must match the file was opened with the permissions and can be a combination of PROT_READ. PROT_WRITE and PROT_EXEC.
The function returns the address in which the file is mapped (caddr_t is usually defined as char*). If 'flag' is MAP_SHARED then store operations will modify the mapped file : In other words, writing to this memory will be equivalent to the write () system call. If 'flag' is MAP_PRIVATE. store operations will work on a copy of the file and will not really change it. The function returns (caddr_t) (1) on the error.
Int munmap (caddr_t addr, size_t entrants);
Unmaps a file. This also happens automatically when the process terminates.
Copying a file using mmap () is much faster than using read () and write (). because there is no need to copy buffers from Kernel to user space and back during the copy. In order to do the copying. follow these steps :
* Open source file with the open (), then map it with mmap ().
* Create destination file with the open ().
* Read the size of the input file using fstat (), then set the size of the destination file to
That same size using lseek (fdout, src_size-1, SEEK_SET) and write (fdout, "" 1).
* Map the destination file with mmap (), with the flag argument MAP_SHARED.
* Call memcpy (dst, src, src_size) to copy the files by memory-to-memory copy.
* Either unmap the files or exit the program.
Memory mapped files can also be used to declare shared memory between processes. The special file "/dev/zero" is an fluctuation stream of zeros when read. and ignores anything written to it. Therefore if a parent process memory-maps this file with MAP_SHARED and initializes this memory. and then forks. the child processes can use the same shared memory pointers to write to this region. The size of the shared memory region to create is the second argument of mmap (). and munmap () can be used to free such memory.
Sockets
Sockets allow client/server computing over a large network such as the Internet. There are two types of them : Server sockets. which passively listen and for requests, and client sockets, which initiate the contact with servers. Once a connection is made. receive both the client and the server can use the usual file descriptors and read () and write () system calls. The connection is full-duplex.
We will only use the TCP protocol here, since it is the most popular. Servers call socket (). bind () and listen () before they can accept () requests; clients just call socket () and then they can already connect () to a server.
Int socket (int domain, int type, int protocol);
Creates an endpoint for communication and returns a descriptor, or -1 on error. The returned descriptor is a "socket descriptor" not a file descriptor. The domain argument is the family of protocols will use the socket AF_UNIX : (internal). AF_INET (Internet), and others. The socket has an associated type as well : SOCK_STREAM (based connection. fifo and reliable such as TCP), SOCK_DGRAM (datagram based, unordered, unreliable such as UDP), SOCK_RAW (simple bytes). SOCK_SEQPACKET and SOCK_DRM. We will use the TCP protocol, so : socket (PF_INET, SOCK_STREAM, 0).
Int bind (int sockfd, struct sockaddr *my_addr, int addrlen);
Gives the socket, sockfd, the local address my_addr. My_addr is addrlen bytes long. Traditionally, this is called "assigning a name to a socket." The exact contents of struct sockaddr defer between protocols; we use TCP and therefore will use this address :
LEAVES OF 13 SPECIES OF LAURACEAE Socket address, internet style. */
Struct sockaddr_in (short sin_family;
U_short sin_port; struct in_addr sin_addr; char sin_zero[8];}
Where sin_family is AF_INET, sin_port and in_addr contain the IP address and port of the computer to bind to. and sin_zero should just be eight (ignored) zeros. The field holds an IP address; in_addr servers should use sockaddr.in_addr.s_addr = INADDR_ANY.
Int listen and (int s, int backlog);
For a connection based protocol (when the socket type is either SOCK_STREAM or SOCK_SEQPACKET). this function declares that the socket is ready to receive requests. and also specifies the length of the queue of waiting requests to allocate. The backlog parameter is limited to 5 (this is a historical bugs).
Int connect (int sockfd, struct sockaddr *serv_addr, int addrlen);
Connects a socket descriptto a remote address. In a client/server program. clients connect using the server 's address in order to start a communication. After connect, the client can simply use as a file descriptor sockfd in calls to read, write, send and recv.
Int accept (int sfd, struct sockaddr *addr, *addrlen int);
Waits until there 's at least one request on the queue for the given socket. Removes a connection request from the queue. and returns a file descriptor for that request. That file descriptor can be used with read, write, send and recv to communicate with the client. The function returns -1 on error; a common error is being interrupted by a signal. in which errno will be set to EINTR.
Int send (int s, const void *msg, practically int, unsigned int flags);
Int recv (int s, void *buf, practically int, unsigned int flags) ;Send and receive data over a socket; read and write can be used as well. but these functions have extra power. Both functions can have a flag of out-of-band MSG_OOB to process data. and recv can have a flag of MSG_PEEK to peek at incoming messages read without removing them from the queue. Flags can be combined using 'or'.
The first three arguments are the same as in read () and write (). except that only sockets can be used. The functions return the number of bytes read/written or -1 on error.
Int getsockname (int s, struct sockaddr *name, *namelen int);
If the 's' is a socket that was bound in the past. this function will write it was bound to the address into the 'name' and 'namelen' arguments.
Unsigned long int htonl (unsigned long int hostlong);
Unsigned short int htons (unsigned short int hostshort);
Unsigned long int ntohl (unsigned long int netlong);
Unsigned short int ntohs (unsigned short int netshort);
Converts integers from the local architecture into network byte order. All integers sent over networks should be in this format. and port numbers given to bind () and connect () and accept () should be in this order as well. In order of appearance. the functions are host to network long (4 bytes), the network host to the short (2 bytes) long network to host. and network to host short. These functions are part of the XDR standard.
Struct hostent *gethostbyname (const char *name);
Struct hostent *gethostbyaddr (const char *addr, practically int, int type);
Retrieve information about a remote computer using either its name ( "www.yahoo.com") or its address (as we have seen. address several types exist).
The hostent structure is defined in the "netdb.h>; as follows:struct hostent --
LEAVES OF 13 SPECIES OF LAURACEAE official name of the host */ char *h_name;
LEAVES OF 13 SPECIES OF LAURACEAE alias list */ char **h_aliases;
Int h_addrtype; LEAVES OF 13 SPECIES OF LAURACEAE host address type, AF_INET at present */
Int h_length LEAVES OF 13 SPECIES OF LAURACEAE The length of the address in bytes.
Char **h_addr_list; LEAVES OF 13 SPECIES OF LAURACEAE zero-terminated array of hosts' network
Addresses in network byte order. */
First address in h_addr_list */ char *h_addr; LEAVES OF 13 SPECIES OF LAURACEAE
}
When using gethostbyname () or gethostbyaddr (). the variable errno and the function perror () won 't work. The two functions will return NULL on error. but in order to know which error occurred and to print an appropriate error message. replace by the following errno and perror (which do the same) :
Extern int h_errno;
Void herror (const char buried);
[/code] |
Inter-Process Communication in Unix
Too chaotic distribution points ~ |
| |